3

我想创建一个Module基于某些标准覆盖注册目标类型的 Autofac。但是,新类型将具有相同的构造函数,并且应该使用与原始类型相同的参数覆盖来创建。

我可以用它AttachToComponentRegistration来决定是否应该覆盖注册,但覆盖本身会带来问题。我想我需要替换IInstanceActivator(特别是ReflectionActivator),但我看不到获取有关现有信息的完整信息的方法ReflectionActivator——例如,似乎没有获取配置参数的属性。

示例(简化代码):

protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry, IComponentRegistration registration) {
    base.AttachToComponentRegistration(componentRegistry, registration);
    var reflectionActivator = ((ComponentRegistration)registration).Activator as ReflectionActivator;
    if (reflectionActivator == null)
        return;

    var replacementType = ReplaceType(reflectionActivator.LimitType);
    if (replacementType == reflectionActivator.LimitType)
        return;

    ((ComponentRegistration)registration).Activator = new ReflectionActivator(
         replacementType,
         reflectionActivator.ConstructorFinder,
         reflectionActivator.ConstructorSelector,
         configuredParameters: ???, // how to get this?
         configuredProperties: ???  // or this?
    );
}

这是可以更容易完成的事情吗?我只是在这里遗漏了一些东西吗?

4

1 回答 1

1

ReflectionActivator 在其私有字段中包含配置参数和配置属性。您可以通过反射阅读它们

var configuredParameters = (IEnumerable<Parameter>)typeof(ReflectionActivator).GetField("_configuredParameters", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(reflectionActivator);

var configuredProperties = (IEnumerable<Parameter>)typeof(ReflectionActivator).GetField("_configuredProperties", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(reflectionActivator);

还有一个工作示例:

class Program
{
    interface IInterface
    {
    }

    class MyClass : IInterface
    {
        private readonly string _name;

        public MyClass(string name)
        {
            _name = name;
        }

        protected MyClass()
        {
        }

        public override string ToString()
        {
            return string.Format("{0} {1}", GetType(), _name);
        }
    }

    class MyReplacementClass : MyClass
    {
        private readonly string _name;

        public MyReplacementClass(string name)
        {
            _name = name;
        }

        public override string ToString()
        {
            return string.Format("{0} {1}", GetType(), _name);
        }
    }

    class MyModule : Module
    {
        protected override void Load(ContainerBuilder builder)
        {
            builder.RegisterType<MyClass>().As<IInterface>().WithParameter("name", "Parameter");
        }

        protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry,
            IComponentRegistration registration)
        {
            var reflectionActivator = ((ComponentRegistration) registration).Activator as ReflectionActivator;
            if (reflectionActivator == null)
                return;

            var replacementType = ReplaceType(reflectionActivator.LimitType);
            if (replacementType == reflectionActivator.LimitType)
                return;

            var configuredParameters = (IEnumerable<Parameter>)typeof(ReflectionActivator).GetField("_configuredParameters",
                BindingFlags.NonPublic | BindingFlags.Instance).GetValue(reflectionActivator);

            var configuredProperties = (IEnumerable<Parameter>)typeof(ReflectionActivator).GetField("_configuredProperties",
                BindingFlags.NonPublic | BindingFlags.Instance).GetValue(reflectionActivator);

            ((ComponentRegistration) registration).Activator = new ReflectionActivator(
                replacementType,
                reflectionActivator.ConstructorFinder,
                reflectionActivator.ConstructorSelector,
                configuredParameters,
                configuredProperties
                );
        }

        private Type ReplaceType(Type limitType)
        {
            return typeof (MyReplacementClass);
        }
    }

    static void Main(string[] args)
    {
        var builer = new ContainerBuilder();
        builer.RegisterModule<MyModule>();

        using (var container = builer.Build())
        {
            var myClass = container.Resolve<IInterface>();
            Console.WriteLine(myClass);
            Console.ReadKey();
        }
    }
}
于 2013-10-23T19:34:48.110 回答