如何动态创建类实例并调用实现

时间:2019-11-07 13:23:40

标签: c# reflection activator

我有各种接口,我需要能够调用它们。这是基类:

public class MyActorBase<TChild>: ActorBase where TChild : MyActorBase<TChild>
{
    public MyActorBase()
    {
       var actors =  ChildClass
           .GetInterfaces()
           .Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IActorMessageHandler<>))
           .Select(x=> (arguments: x.GetGenericArguments(), definition: x))
           .ToImmutableList();

       if (actors.Any())
       {
           var ty = actors.First();
           var obj = Activator.CreateInstance(ty.definition, true);

           // how to call method implementation
       }

    }

    protected sealed override bool Receive(object message) => false;
    private Type ChildClass => ((this as TChild)?? new object()).GetType();
}


public interface IActorMessageHandler<in T>
{
    Task Handle(T msg);
}

我阅读了这些博客文章:

  1. Dont use Activator.CreateInstance
  2. Linq Expressions
  3. Creating objects performance implications

作者在编译时已经知道类型,因此可以正确地进行类型转换。我在编译时一无所知,因此无法使用通用方法或使用()运算符或as运算符进行类型转换。

  

更新:我认为人们对我想要实现的目标并不了解。所以考虑一下。我做了一个裸包,任何人都可以   取决于。在世界某个地方,有人编写了以下代码:

    public class MyMessage
    {
        public int Number { get; }

        public MyMessage(int number) => Number = number;
    }

    public class MyNewActor: MyActorBase<MyNewActor>, IActorMessageHandler<MyMessage>
    {
        public Task Handle(MyMessage msg)
        {
            return Task.CompletedTask;
        }
    }

我希望任何实现 IActorMessageHandler 的类,我都应该能够调用其方法 Handle(T msg)。所以当我能够实例化它时(考虑到我没有使用任何依赖注入),如何才能以最有效的方式调用该方法?

还有其他替代方法吗?

2 个答案:

答案 0 :(得分:1)

如何使用dynamic关键字?基本上,这是为您精心包装的优化反射:

dynamic obj = Activator.CreateInstance(ty.definition, true);
Task t = obj.Handle(msg); //need to define msg before

它绕过编译时检查并在运行时推迟方法查找。

请注意,如果无法执行Handle方法的解析,它将在运行时失败。

This blog post的结论是,dynamic由于缓存优化而经常被调用时比反射快得多。

答案 1 :(得分:1)

您不应该使用Activator.CreateInstance,这非常昂贵。相反,您可以使用Expression.Lamda高效地创建对象。

  var object =  Expression.Lambda<Func<IActorMessageHandler<TChild>>>(Expression.New(ty.definition.Value.GetConstructor(Type.EmptyTypes) ?? throw new 
    Exception("Failed to create object"))
                        ).Compile()();
相关问题