Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 添加Autofac扩展以在未适当注入批准类型时引发异常_C#_Dependency Injection_Autofac - Fatal编程技术网

C# 添加Autofac扩展以在未适当注入批准类型时引发异常

C# 添加Autofac扩展以在未适当注入批准类型时引发异常,c#,dependency-injection,autofac,C#,Dependency Injection,Autofac,我正在尝试创建一个Autofac扩展方法,该方法将在为非核准对象类型的对象创建注册类型时引发异常 public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> OnlyForInheritorsOf<TLimit, TReflectionActivatorData, TStyle>( this IRegistrationBuilder<TLimit, TReflect

我正在尝试创建一个Autofac扩展方法,该方法将在为非核准对象类型的对象创建注册类型时引发异常

public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> OnlyForInheritorsOf<TLimit, TReflectionActivatorData, TStyle>(
    this IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> registration, Type baseType)
where TReflectionActivatorData : ReflectionActivatorData
{
    return registration.OnActivated(e =>
    {
        if (!baseType.IsInstanceOfType(??? instance of target/receiver ???))
            throw new InvalidOperationException("Expected to implement");
    });
}
public静态IRegistrationBuilder仅适用于(
此IRegistrationBuilder注册,类型为baseType)
其中TReflectionActivatorData:ReflectionActivatorData
{
返回注册。已激活(e=>
{
如果(!baseType.IsInstanceOfType(?目标/接收器实例??)
抛出新的InvalidOperationException(“预计将实施”);
});
}

e.Instance
指向刚创建/激活的对象。但是,我需要关于我们要给它的对象的信息。如何获取该信息?

如果您需要指定某些注册需要特定类型,而其他注册需要另一种类型,您应该查看

例如,如果您有两个用于
IFoo
的实现,您可以这样注册它们

builder.RegisterType<Foo1>().Named<IFoo>("foo1");
builder.RegisterType<Foo2>().Named<IFoo>("foo2");
或者使用
Bar
constructor上的属性指定键:

public class Bar
{
    public Bar([WithKey("foo1")]IFoo foo)
    { }
}
我不知道您的具体场景,它可能需要一些代码重构,但这些更改可能比使用更复杂的场景更好


顺便说一下,如果你真的想做你解释的事情。我编写了一些代码,使用自定义的
参数
模块
,如果调用方不是注册所需的类型,则会引发异常

public static class RegistrationExtensions
{
    public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> OnlyForInheritorsOf<TLimit, TReflectionActivatorData, TStyle>(this IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> registration, Type baseType)
            where TReflectionActivatorData : ReflectionActivatorData
    {
        registration.RegistrationData.Metadata.Add(RestrictingRegistrationModule.MetadataKey, baseType);
        return registration;
    }
}

public class RestrictingRegistrationModule : Autofac.Module
{
    internal const String MetadataKey = "RestrictedType";


    internal class RestrictedAutowiringParameter : Parameter
    {
        public RestrictedAutowiringParameter(RestrictingRegistrationModule restrictingRegistrationModule)
        {
            this._restrictingRegistrationModule = restrictingRegistrationModule;
        }


        private readonly RestrictingRegistrationModule _restrictingRegistrationModule;


        public override Boolean CanSupplyValue(ParameterInfo pi, IComponentContext context, out Func<Object> valueProvider)
        {
            if (pi == null)
            {
                throw new ArgumentNullException("pi");
            }
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            IInstanceLookup lookup = context as IInstanceLookup;
            if (lookup != null)
            {
                IComponentRegistration registration;
                if (context.ComponentRegistry.TryGetRegistration(new TypedService(pi.ParameterType), out registration))
                {
                    Type restrictedType;
                    if (this._restrictingRegistrationModule.RestrictedRegistrations.TryGetValue(registration, out restrictedType))
                    {
                        Type callerType = lookup.ComponentRegistration.Activator.LimitType;
                        if (!(callerType == restrictedType || callerType.IsSubclassOf(restrictedType)))
                        {
                            throw new Exception(String.Format("Registration {0} is not compatible for type {1}", registration, callerType));
                        }
                    }

                    valueProvider = (() => context.ResolveComponent(registration, Enumerable.Empty<Parameter>()));
                    return true;
                }
            }

            valueProvider = null;
            return false;
        }
    }


    public RestrictingRegistrationModule()
    {
        this._restrictedRegistrations = new Dictionary<IComponentRegistration, Type>();
    }


    private readonly Dictionary<IComponentRegistration, Type> _restrictedRegistrations;


    public Dictionary<IComponentRegistration, Type> RestrictedRegistrations
    {
        get
        {
            return this._restrictedRegistrations;
        }
    }


    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration)
    {
        base.AttachToComponentRegistration(componentRegistry, registration);

        Object value;
        if (registration.Metadata.TryGetValue(RestrictingRegistrationModule.MetadataKey, out value))
        {
            this._restrictedRegistrations.Add(registration, (Type)value);
        }

        registration.Preparing += (sender, e) =>
        {
            e.Parameters = e.Parameters.Concat(new Parameter[] { new RestrictedAutowiringParameter(this) });
        };
    }

}
公共静态类注册扩展
{
公共静态IRegistrationBuilder仅适用于的所有者(此IRegistrationBuilder注册,类型baseType)
其中TReflectionActivatorData:ReflectionActivatorData
{
registration.RegistrationData.Metadata.Add(restrictionRegistrationModule.MetadataKey,baseType);
申报登记;
}
}
公共类限制注册模块:自动传真模块
{
内部常量字符串MetadataKey=“RestrictedType”;
内部类受限自动布线参数:参数
{
public RestrictedAutowiring参数(限制注册模块限制注册模块)
{
这._restrictingRegistrationModule=restrictingRegistrationModule;
}
私有只读限制注册模块_限制注册模块;
公共重写布尔值CanSupplyValue(ParameterInfo pi、IComponentContext上下文、out Func valueProvider)
{
if(pi==null)
{
抛出新的ArgumentNullException(“pi”);
}
if(上下文==null)
{
抛出新的ArgumentNullException(“上下文”);
}
IInstanceLookup lookup=作为IInstanceLookup的上下文;
if(查找!=null)
{
i组件注册;
if(context.ComponentRegistry.TryGetRegistration(新类型服务(pi.ParameterType),out注册))
{
类型限制型;
if(this.\u restrictingRegistrationModule.RestrictedRegistrations.TryGetValue(registration,out restrictedType))
{
类型callerType=lookup.ComponentRegistration.Activator.LimitType;
如果(!(callerType==restrictedType | | callerType.IsSubclassOf(restrictedType)))
{
抛出新异常(String.Format(“注册{0}与类型{1}”、注册、调用类型不兼容”);
}
}
valueProvider=(()=>context.ResolveComponent(注册,Enumerable.Empty());
返回true;
}
}
valueProvider=null;
返回false;
}
}
公共限制注册模块()
{
这是。_restrictedRegistrations=newdictionary();
}
私人只读词典(受限制的注册);;
公共词典限制注册
{
得到
{
返回此项。\u受限注册;
}
}
受保护的覆盖无效AttachToComponentRegistration(IComponentRegistry ComponentRegistration,IComponentRegistration注册)
{
基本。附件组件注册(组件注册,注册);
目标价值;
if(registration.Metadata.TryGetValue(restrictionRegistrationModule.MetadataKey,out值))
{
此._restrictedRegistrations.Add(注册,(类型)值);
}
注册。准备+=(发件人,e)=>
{
e、 Parameters=e.Parameters.Concat(新参数[]{new RestrictedAutowiringParameter(this)});
};
}
}
您可以这样使用此代码:

builder.RegisterType<Bar>()
        .As<Bar>()
        .WithParameter((pi, c) => pi.ParameterType == typeof(IFoo), 
                       (pi, c) => c.ResolveNamed<IFoo>("foo1")); 
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterModule(new RestrictingRegistrationModule());
builder.RegisterType<Bar>().As<Bar>();
builder.RegisterType<Bar2>().As<Bar2>();
builder.RegisterType<Foo>().As<IFoo>().OnlyForInheritorsOf(typeof(Bar));

IContainer container = builder.Build();

Bar bar = container.Resolve<Bar>();
Bar2 bar2 = container.Resolve<Bar2>(); // will throw
ContainerBuilder=newcontainerbuilder();
注册模块(新的限制注册模块());
builder.RegisterType().As();
builder.RegisterType().As();
builder.RegisterType().As()。仅适用于(typeof(Bar));
IContainer容器=builder.Build();
Bar=container.Resolve();
Bar2 Bar2=container.Resolve();//会扔

我没有深入测试这段代码,它只是为了好玩和教育的目的,小心使用

谢谢你的模块!那是不平凡的。我完全了解命名实例方法。然而,它不能很好地扩展。