How to create the class instances dynamically and call the implementation

亡梦爱人 提交于 2020-01-25 08:02:45

问题


I have various interfaces and I need to be able to call them. Here is the base class:

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);
}

I read these blog post:

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

The writers already knew the type at compile time hence were able to cast correctly. I do not know anything at compile time so I cannot use a generic method or typecast it using () operator or as operator.

UPDATE: I think people are not getting the idea of what I want to achieve. so consider this. I made a nuget package which anyone can depend upon. Somewhere in the world, someone writes this code:

    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;
        }
    }

I want that any class that implements the IActorMessageHandler, i should be able to call its method Handle(T msg). so while I was able to instantiate it (considering that I'm not using any dependency injection) how can I call the method in the most efficient way?

Is there any alternate to reflection?


回答1:


you should not use Activator.CreateInstance it's very much expensive. instead, you may use Expression.Lamda to create objects in an efficient way.

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



回答2:


What about using the dynamic keyword? This is basically optimized reflection nicely wrapped for you:

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

It bypasses compile-time checks and defers method look-up at run-time.

Note that it will fail at run-time if no resolution for the Handle method can be performed.

This blog post concludes that dynamic ends up being much quicker than reflection when called fairly often because of caching optimizations.



来源:https://stackoverflow.com/questions/58749696/how-to-create-the-class-instances-dynamically-and-call-the-implementation

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!