C# 如何使用自动注册确定单个库的范围

C# 如何使用自动注册确定单个库的范围,c#,dependency-injection,simple-injector,C#,Dependency Injection,Simple Injector,如果要自动注册/发现依赖项,是否可以为一个、两个或x个特定程序集设置/更改依赖项生存期范围选项(瞬态、单个、PerWebReqest等)?我有下面的示例代码: public class RegistrationPackage : IPackage { public void RegisterServices(Container container) { var @namespace = "ConsoleLib"; var assemblies = AppD

如果要自动注册/发现依赖项,是否可以为一个、两个或x个特定程序集设置/更改依赖项生存期范围选项(瞬态、单个、PerWebReqest等)?我有下面的示例代码:

public class RegistrationPackage : IPackage
{
    public void RegisterServices(Container container)
    {
        var @namespace = "ConsoleLib";
    var assemblies = AppDomain.CurrentDomain.GetAssemblies()
        .Where(a => a.FullName.StartsWith(@namespace))
        .Select(a => a).ToList();

    var names = assemblies.Select(a => a.FullName);

    Action<string> poormanslogger = Console.WriteLine;
    //poormanslogger = Trace.WriteLine;

    foreach (var name in names)
        poormanslogger("Located the following assemblies: " + name);

    // could combine these two and remove the if statement for the open generic registrations below
    //container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>), AppDomain.CurrentDomain.GetAssemblies());

    foreach (var assembly in assemblies)
        foreach (var type in assembly.GetExportedTypes().Where(a => !a.IsAbstract))
        {
            poormanslogger(string.Format("Exported Type: {0}", type.Name));
            foreach (var @interface in type.GetInterfaces())
            {
                poormanslogger(string.Format("\tInterface type: {0}", @interface.Name));
                // register open generic
                if (@interface.IsGenericType && !type.IsAbstract && type.IsGenericType)
                    container.RegisterManyForOpenGeneric(type, assemblies);
                // register closed generic
                if (@interface.IsGenericType && !type.IsAbstract && !type.IsGenericType)
                    container.Register(@interface, type, Lifestyle.Transient);
                // register non generic
                if (!type.IsGenericType && !@interface.IsGenericType && !type.IsAbstract)
                    container.Register(@interface, type, Lifestyle.Transient);
            }

            // unregistered type fall back...
            //container.RegisterOpenGeneric(typeof(ICommandHandler<>), typeof(UnRegisteredCommandHandler<>));
        }

    // The decorators are applied in the order in which they are registered
    container.RegisterDecorator(typeof(ICommandHandler<>),
            typeof(TransactionCommandHandlerDecorator<>));

    container.RegisterDecorator(typeof(ICommandHandler<>),
        typeof(DeadlockRetryCommandHandlerDecorator<>));

    container.RegisterDecorator(typeof(ICommandHandler<>),
        typeof(ValidationCommandHandlerDecorator<>));

    container.RegisterDecorator(typeof(ICommandHandler<>),
        typeof(SecurityCommandHandlerDecorator<>));
}
}
公共类注册包:IPackage
{
公共无效注册表服务(容器)
{
var@namespace=“ConsoleLib”;
var assemblies=AppDomain.CurrentDomain.GetAssemblys()
.Where(a=>a.FullName.StartsWith(@namespace))
.Select(a=>a.ToList();
var name=assemblies.Select(a=>a.FullName);
Action poormanslogger=Console.WriteLine;
//poormanslogger=Trace.WriteLine;
foreach(名称中的变量名称)
poormanslogger(“位于以下组件:“+名称”);
//可以将这两者结合起来,并删除下面打开的通用注册的if语句
//container.RegisterManyForOpenGeneric(typeof(ICommandHandler),AppDomain.CurrentDomain.GetAssemblys());
foreach(程序集中的变量程序集)
foreach(assembly.GetExportedTypes()中的变量类型,其中(a=>!a.IsAbstract))
{
poormanslogger(string.Format(“导出的类型:{0}”,Type.Name));
foreach(type.GetInterfaces()中的var@interface)
{
poormanslogger(string.Format(“\tInterface类型:{0},@interface.Name));
//注册开放泛型
if(@interface.IsGenericType&&!type.IsAbstract&&type.IsGenericType)
container.RegisterManyForOpenGeneric(类型、程序集);
//寄存器闭合泛型
if(@interface.IsGenericType&&!type.isAssert&&!type.IsGenericType)
container.Register(@interface,type,lifety.Transient);
//寄存器非泛型
如果(!type.IsGenericType&&!@interface.IsGenericType&&!type.isAssert)
container.Register(@interface,type,lifety.Transient);
}
//未注册类型回退。。。
//RegisterOpenGeneric(typeof(ICommandHandler),typeof(UnRegisteredCommandHandler));
}
//装饰器按注册顺序应用
容器.注册表记录器(类型为(ICommandHandler),
类型(TransactionCommandHandlerDecorator));
容器.注册表记录器(类型为(ICommandHandler),
类型(DeadlockRetryCommandHandlerDecorator);
容器.注册表记录器(类型为(ICommandHandler),
类型(ValidationCommandHandlerDecorator));
容器.注册表记录器(类型为(ICommandHandler),
类型(SecurityCommandHandlerDecorator);
}
}
然后我有标准的东西:

    var container = new Container();

    container.RegisterPackages();

    container.Verify();

    var instance = container.GetInstance<ICommandHandler<UnregisteredCommand>>();
    instance.Handle(new UnregisteredCommand());
var container=newcontainer();
container.RegisterPackages();
container.Verify();
var instance=container.GetInstance();
Handle(新的UnregisteredCommand());

我可以使用ExpressionBuilding活动吗

Simple Injector提供的批量注册功能限制了通用类型的注册。文件说明了为什么:

尽管许多其他DI库包含高级API来执行 基于约定的注册,我们发现使用自定义 LINQ查询更易于编写,更易于理解,并且可以经常使用 证明它比使用预定义和限制性API更灵活

但是,即使是针对通用接口类型的批量注册,也没有内置的支持来区分不同的生活方式。这是经过深思熟虑的,因为这将迫使您在类上放置库定义的属性来描述生活方式,并且这将使您的应用程序依赖于简单的注入器,这是一件非常重要的事情

简单喷油器2.6引入了一个新的扩展点,称为。当没有明确提供生活方式时,此扩展点允许您覆盖框架的默认选择行为。默认行为是使用
生活方式.Transient

如果需要类似的内容,则应覆盖默认的生活方式选择行为,并创建一个可应用于组件的属性。可能看起来像这样:

public enum CreationPolicy { Transient, Scoped, Singleton };

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface,
    Inherited = false, AllowMultiple = false)]
public sealed class CreationPolicyAttribute : Attribute {
    public CreationPolicyAttribute(CreationPolicy policy) {
        this.Policy = policy;
    }

    public CreationPolicy Policy { get; private set; }
}
应在应用程序的基础项目中定义此属性,以便可以用它标记每个类:

[CreationPolicy(CreationPolicy.Scoped)]
public class CustomerRepository : IRepository<Customer>
{
    public CustomerRepository(DbContext context) { }

    public Customer GetById(Guid id) {
        // etc.
    }
}
有了这一点,我们简化了批量注册,我们不必做任何特殊的事情来选择合适的生活方式:

container.RegisterOpenGeneric(
    typeof(ICommandHandler<>),
    AppDomain.CurrentDomain.GetAssemblies());

var registrations =
    from assembly in assemblies
    from type in assembly.GetExportedTypes()
    where !type.IsAbstract && !type.IsGenericType
    from @interface in type.GetInterfaces()
    where !@interface.IsGenericType
    select new { Service = @interface, Implementation = type };

foreach (var registration in registrations)
{
    container.Register(registration.Service, registration.Implementation);
}
container.RegisterOpenGeneric(
类型(ICommandHandler),
AppDomain.CurrentDomain.GetAssemblys());
风险值登记=
从程序集中的程序集
来自程序集中的类型。GetExportedTypes()
哪里type.isastract&!type.IsGenericType
从类型.GetInterfaces()中的@interface开始
哪里@interface.IsGenericType
选择新建{Service=@interface,Implementation=type};
foreach(注册中的var注册)
{
容器.注册(注册.服务,注册.实施);
}
另一个选项不是覆盖生活方式选择行为,而是让所有内容都注册为瞬态(因为这将是一个合理的默认设置),而是覆盖那些应该注册的少数注册:

container.RegisterOpenGeneric(
    typeof(ICommandHandler<>),
    AppDomain.CurrentDomain.GetAssemblies());

container.Options.EnableOverridingRegistrations = true;

container.Register<ICommandHandler<SpecialOperation>, SpecialOperationHandler>(
    scopedLifestyle);

container.Options.EnableOverridingRegistrations = false;
container.RegisterOpenGeneric(
类型(ICommandHandler),
AppDomain.CurrentDomain.GetAssemblys());
container.Options.EnableOverridingRegistrations=true;
集装箱。登记(
scopedLifestyle);
container.Options.EnableOverridingRegistrations=false;

很抱歉,但不清楚您想要实现什么目标以及您的问题是什么。你说的“范围选择”是什么意思?对不起,我睡不着觉有点累了。。。在任何情况下,我指的都是生命周期范围,比如PerWebRequest、Single、Transient等等。。。我会更新我的问题。我仍然不确定你在问什么。但是我对你的自动注册有点惊讶
container.RegisterOpenGeneric(
    typeof(ICommandHandler<>),
    AppDomain.CurrentDomain.GetAssemblies());

var registrations =
    from assembly in assemblies
    from type in assembly.GetExportedTypes()
    where !type.IsAbstract && !type.IsGenericType
    from @interface in type.GetInterfaces()
    where !@interface.IsGenericType
    select new { Service = @interface, Implementation = type };

foreach (var registration in registrations)
{
    container.Register(registration.Service, registration.Implementation);
}
container.RegisterOpenGeneric(
    typeof(ICommandHandler<>),
    AppDomain.CurrentDomain.GetAssemblies());

container.Options.EnableOverridingRegistrations = true;

container.Register<ICommandHandler<SpecialOperation>, SpecialOperationHandler>(
    scopedLifestyle);

container.Options.EnableOverridingRegistrations = false;