Scorpio 常规性操作
什么是 Scorpio 常规性操作
Conventional
用于对应用 Assembly
中的 Type
执行一些常规操作。如:自动的依赖关系注入、Aspect 注入、Unit Of Work 注入等。
Conventional
主要由以下类、接口及方法组成:
ConventionalAction
类,用于对执行一般性操作。ConventionalRegistrar
类,用于注册及配置ConventionalAction
类。ServiceCollection.AddConventionalRegistrar()
方法,用于将ConventionalRegistrar
添加到ConventionalRegistrar
列表中。ServiceCollection.RegisterAssemblyByConvention()
方法,用于对指定的Assembly
执行ConventionalAction
操作。
在 Scorpio 中,各种自动化操作便是基于 Conventional 设计并实现的。如果您需要实现自己的一般性操作。请实现 ConventionalActionBase
抽象类及 IConventionalRegistrar
接口。以下为 Scorpio 的 Dependency Injection 组件的实现代码:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using Scorpio.Conventional;
using Scorpio.DependencyInjection.Conventional;
using System.Linq.Expressions;
namespace Scorpio.DependencyInjection.Conventional
{
internal class BasicConventionalRegistrar : IConventionalRegistrar
{
public void Register(IConventionalRegistrationContext context)
{
context.DoConventionalAction<ConventionalDependencyAction>(config =>
{
config
.Where(t => t.IsStandardType())
.Where(t => t.IsAssignableTo<ISingletonDependency>())
.AsDefault().AsSelf().Lifetime(ServiceLifetime.Singleton);
config
.Where(t => t.IsStandardType())
.Where(t => t.IsAssignableTo<ITransientDependency>())
.AsDefault().AsSelf().Lifetime(ServiceLifetime.Transient);
config
.Where(t => t.IsStandardType())
.Where(t => t.IsAssignableTo<IScopedDependency>())
.AsDefault().AsSelf().Lifetime(ServiceLifetime.Scoped);
config
.Where(t => t.IsStandardType())
.Where(t => t.AttributeExists<ExposeServicesAttribute>(false))
.AsExposeService();
});
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Scorpio.Conventional;
namespace Scorpio.DependencyInjection.Conventional
{
class ConventionalDependencyAction : ConventionalActionBase
{
public ConventionalDependencyAction(IConventionalConfiguration configuration)
: base(configuration)
{
}
protected override void Action(IConventionalContext context)
{
context.Types.ForEach(
t => context.Get<ICollection<IRegisterAssemblyServiceSelector>>("Service").ForEach(
selector => selector.Select(t).ForEach(
s => context.Services.ReplaceOrAdd(
ServiceDescriptor.Describe(s, t,
context.GetOrAdd<IRegisterAssemblyLifetimeSelector>("Lifetime",
new LifetimeSelector(ServiceLifetime.Transient)).Select(t)),
t.GetAttribute<ReplaceServiceAttribute>()?.ReplaceService??false
))));
}
}
}
ConventionalActionBase 类
您如果需要对类执行一些常规的操作,您首先需要继承 ConventionalActionBase
类并重写这个类的 Action(IConventionalContext context)
方法。如:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Scorpio.Conventional;
namespace Scorpio.DependencyInjection.Conventional
{
class ConventionalDependencyAction : ConventionalActionBase
{
public ConventionalDependencyAction(IConventionalConfiguration configuration)
: base(configuration)
{
}
protected override void Action(IConventionalContext context)
{
context.Types.ForEach(t=> {
//TODO: Do something for the type.
})
}
}
}
IConventionalRegistrar
在编写完成常规操作代码后,我们需要实现 IConventionalRegistrar
接口以便将编写好的操作代码注册并配置到 Conventional
中,如:
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using Scorpio.Conventional;
using Scorpio.DependencyInjection.Conventional;
using System.Linq.Expressions;
namespace Scorpio.DependencyInjection.Conventional
{
internal class BasicConventionalRegistrar : IConventionalRegistrar
{
public void Register(IConventionalRegistrationContext context)
{
context.DoConventionalAction<ConventionalDependencyAction>(config =>
{
config.CreateContext().Where(t=>/*添加过滤条件*/);
//或者
config.Where(t=>/*添加过滤条件*/);//这是个快捷方法,和上面的语句等效。
});
}
}
}
最后,请调用 ServiceCollection.AddConventionalRegistrar()
方法将我们的注册器添加到 Scorpio 中。注册器将在调用 ServiceCollection.RegisterAssemblyByConvention()
或者它的重载方法时被依次调用。 如:
using System;
using System.Collections.Generic;
using System.Text;
using Scorpio.Modularity;
using Scorpio.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;
using Scorpio.Conventional;
using Scorpio.DependencyInjection.Conventional;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Options;
using Scorpio.Threading;
using Scorpio.Runtime;
namespace Scorpio
{
/// <summary>
///
/// </summary>
internal sealed class StartupModule : ScorpioModule
{
public override void PreConfigureServices(ConfigureServicesContext context)
{
context.Services.AddConventionalRegistrar(new BasicConventionalRegistrar());
}
/// <summary>
///
/// </summary>
/// <param name="context"></param>
public override void ConfigureServices(ConfigureServicesContext context)
{
context.Services.RegisterAssemblyByConvention();
}
}
}
请注意:
请在
PreConfigureServices()
方法中调用AddConventionalRegistrar()
方法,而在ConfigureServices()
方法中调用RegisterAssemblyByConvention()
方法,以确保在调用任何RegisterAssemblyByConvention()
之前所有的注册器已经就绪。