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()之前所有的注册器已经就绪。