我有各种接口,我需要能够调用它们。这是基类:
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);
}
我阅读了这些博客文章:
作者在编译时已经知道类型,因此可以正确地进行类型转换。我在编译时一无所知,因此无法使用通用方法或使用()运算符或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)。所以当我能够实例化它时(考虑到我没有使用任何依赖注入),如何才能以最有效的方式调用该方法?
还有其他替代方法吗?
答案 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()();