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

C# 如何动态创建类实例并调用实现,c#,reflection,activator,C#,Reflection,Activator,我有各种接口,我需要能够调用它们。下面是基类: public class MyActorBase<TChild>: ActorBase where TChild : MyActorBase<TChild> { public MyActorBase() { var actors = ChildClass .GetInterfaces() .Where(i => i.IsGenericType

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

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);
}
公共类MyActorBase:ActorBase其中TChild:MyActorBase
{
公共MyActorBase()
{
var=ChildClass
.GetInterfaces()
.Where(i=>i.IsGenericType&&i.GetGenericTypeDefinition()==typeof(IActorMessageHandler))
.Select(x=>(参数:x.GetGenericArguments(),定义:x))
.ToImmutableList();
if(actors.Any())
{
var ty=actors.First();
var obj=Activator.CreateInstance(ty.definition,true);
//如何调用方法实现
}
}
受保护的密封覆盖布尔接收(对象消息)=>false;
私有类型ChildClass=>((作为TChild)??新对象()).GetType();
}
公共接口IActorMessageHandler
{
任务句柄(T msg);
}
我读了以下博文:

  • 编写者在编译时已经知道类型,因此能够正确地转换。在编译时我什么都不知道,所以我不能使用泛型方法,也不能使用()运算符或as运算符对其进行类型转换

    更新:我认为人们没有意识到我想要实现什么。所以考虑一下这个。我做了一个任何人都能做的nuget包 依赖于。在世界的某个地方,有人编写了以下代码:

    公共类MyMessage
    {
    公共整数{get;}
    公共MyMessage(整数)=>number=number;
    }
    公共类MyNewActor:MyActorBase,IActorMessageHandler
    {
    公共任务句柄(MyMessage msg)
    {
    返回Task.CompletedTask;
    }
    }
    

    我希望实现IActorMessageHandler的任何类都能够调用其方法Handle(tmsg)。因此,虽然我能够实例化它(考虑到我没有使用任何依赖项注入),但如何以最有效的方式调用该方法


    除了反射还有其他选择吗?

    使用
    动态
    关键字怎么样?这基本上是为您精心包装的优化反射:

    dynamic obj=Activator.CreateInstance(ty.definition,true);
    任务t=对象句柄(msg)//需要定义味精之前
    
    它绕过编译时检查,并在运行时延迟方法查找

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


    得出的结论是,由于缓存优化,
    dynamic
    在频繁调用时比reflection快得多。

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

    dynamic obj=Activator.CreateInstance(ty.definition,true);
    任务t=对象句柄(msg)//需要定义味精之前
    
    它绕过编译时检查,并在运行时延迟方法查找

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


    得出的结论是,由于缓存优化,
    dynamic
    在相当频繁地调用时比reflection快得多。

    您不应该使用
    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()();
    
    var object=Expression.Lambda(Expression.New(ty.definition.Value.GetConstructor(Type.EmptyTypes))抛出新
    异常(“未能创建对象”))
    ).Compile();
    
    您不应该使用
    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()();
    
    var object=Expression.Lambda(Expression.New(ty.definition.Value.GetConstructor(Type.EmptyTypes))抛出新
    异常(“未能创建对象”))
    ).Compile();
    
    您尝试过什么?您应该能够使用与发现和创建实例相同的反射代码。问题是所有的博客在编译时都知道这个类,所以他们正确地键入它。我的情况不同。我在编译时不知道这个类,所以我不能使用类型转换或者甚至作为操作符来类型转换它。所以你还没有找到这个或者?“我怎样才能以最有效的方式调用这个方法?”-如果你在构造函数中做所有反射和LINQ,坦白说,“高效”已经飞出了窗口。。。您可能希望将
    actors
    移动为
    静态只读
    字段,以便只构建一次?(可能使用
    typeof(TChild)
    或其他东西,而不是
    将其作为TChild
    东西?)另一个选项是使消息处理程序接口非通用。然后就可以直接调用了。你试过什么?您应该能够使用与发现和创建实例相同的反射代码。问题是所有的博客在编译时都知道这个类,所以他们正确地键入它。我的情况不同。我在编译时不知道这个类,所以我不能使用类型转换或者甚至作为操作符来类型转换它。所以你还没有找到这个或者?“我怎样才能以最有效的方式调用这个方法?”-如果你在构造函数中做所有反射和LINQ,坦白说,“高效”已经飞出了窗口。。。您可能希望将
    actors
    移动为
    静态只读
    字段,以便只构建一次?(可能使用
    typeof(TChild)
    或其他东西,而不是
    将其作为TChild
    东西?)另一个选项是使消息处理程序接口非通用。然后可以直接调用它。它比繁琐的MethodInfo和Invoke()快吗?是的,对