首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从TypeInfo和MethodInfo创建Func<Type>

从TypeInfo和MethodInfo创建Func<Type>
EN

Stack Overflow用户
提问于 2017-06-17 01:50:42
回答 2查看 384关注 0票数 0

我很好奇是否有可能在手头只有一个类型的情况下创建一个委托。如下所示:

代码语言:javascript
运行
复制
var concreteType = DiscoverTypeInRuntime();
var methodName = "SomeNameIKnowInAdvance";
var methodInfo = concreteType.GetMethodInfo(methodName);
var dynamicallyConstructedFunc = DynamicallyConstructFunc(methodInfo)

委托的类型应为

代码语言:javascript
运行
复制
Func<ConcreteType>

更新:

确切的类型事先是未知的。它是在程序运行时发现的。委托的类型不能为Func<object,只允许使用Func<ConcreteType>。已知其名称的方法是工厂方法,它返回ConcreteType的一个实例,从而满足需求。

更新2:

我将在这里提供一些代码来解释用例。希望这能澄清这个问题:

代码语言:javascript
运行
复制
public class LoginProviderBuilder : FakeBuilderBase<ILoginProvider>
{        
    private readonly Dictionary<string, string> _users = new Dictionary<string, string>();

    private LoginProviderBuilder()
    {

    }
    //...
}

public class Module : ProvidersModuleBase
{
    protected override void OnRegisterProviders(IIocContainerRegistrator iocContainer)
    {
        base.OnRegisterProviders(iocContainer);
        RegisterAllBuilders(iocContainer, LoginProviderBuilder.CreateBuilder);
        RegisterAllBuilders(iocContainer, WarehouseProviderBuilder.CreateBuilder);
        RegisterAllBuilders(iocContainer, EventsProviderBuilder.CreateBuilder);
    }
}

protected void RegisterAllBuilders<TProvider>(IIocContainerRegistrator iocContainerRegistrator, 
        Func<FakeBuilderBase<TProvider>> defaultBuilderCreationFunc) where TProvider : class
    {
        var builders = BuildersCollectionContext.GetBuilders<TProvider>().ToArray();
        if (builders.Length == 0)
        {
            RegistrationHelper.RegisterBuilder(iocContainerRegistrator, defaultBuilderCreationFunc());
        }
        else
        {
            foreach (var builder in builders)
            {
                RegistrationHelper.RegisterBuilder(iocContainerRegistrator, builder);
            }
        }
    }

简而言之,手头的任务是动态发现所有符合条件的构建器类型,并自动注册它们,同时以某种方式保留具体类型和现有的泛型API。

如果这段代码不清楚,您可以在此处找到示例解决方案:https://github.com/LogoFX/Samples.Specifications

EN

回答 2

Stack Overflow用户

发布于 2017-06-17 01:56:38

在一些反射的帮助下,你可以构造一个这样做的函数:

代码语言:javascript
运行
复制
private Func<T> GetDelegateFromMethodName<T>(string methodName)
{
    var type = typeof(T);
    var method = type.GetMethods().FirstOrDefault(m => m.Name == methodName);
    if (method == null)
    {
        throw new ArgumentException(nameof(methodName));
    }
    return (Func<T>) Delegate.CreateDelegate(typeof(Func<T>), method);
}

下面是一个用法示例:

代码语言:javascript
运行
复制
var methodName = "SomeNameIKnowInAdvance";
var dynamicallyConstructedFunc = GetDelegateFromMethodName<ConcreteClass>(methodName);

请记住,这只适用于静态方法,如果你想让它也适用于实例方法,你还需要传递一个实例:

代码语言:javascript
运行
复制
private Func<T> GetDelegateFromMethodName<T>(T instance, string methodName)
{
    var type = typeof(T);
    var method = type.GetMethods().FirstOrDefault(m => m.Name == methodName);
    if (method == null)
    {
        throw new ArgumentException(nameof(methodName));
    }
    return (Func<T>) Delegate.CreateDelegate(typeof(Func<T>), instance, method);
}

它的一个示例用法是:

代码语言:javascript
运行
复制
var methodName = "ConstructClass";
var dynamicallyConstructedFunc = GetDelegateFromMethodName<ConcreteClass>(new ConcreteClass(), methodName);

如果你不喜欢泛型,你也可以使用object,但这不会导致Func<ConcreteClass>,你必须手动转换它:

代码语言:javascript
运行
复制
private Func<object> GetDelegateFromMethodName(object instance, string methodName)
{
    var type = instance.GetType();
    var method = type.GetMethods().FirstOrDefault(m => m.Name == methodName);
    if (method == null)
    {
        throw new ArgumentException(nameof(methodName));
    }
    return (Func<object>) Delegate.CreateDelegate(typeof(Func<object>), instance, method);
}

private Func<object> GetDelegateFromMethodName(Type type, string methodName)
{
    var method = type.GetMethods().FirstOrDefault(m => m.Name == methodName);
    if (method == null)
    {
        throw new ArgumentException(nameof(methodName));
    }
    return (Func<object>)Delegate.CreateDelegate(typeof(Func<object>), method);
}
票数 3
EN

Stack Overflow用户

发布于 2017-06-18 15:39:48

您可以创建这样的委托-但您只能将其作为Delegate引用,因为您不知道编译时的实际类型。它需要使用MakeGenericTypeFunc<T>创建适当的委托类型。

代码语言:javascript
运行
复制
var concreteType = DiscoverTypeInRuntime();
var methodName = "SomeNameIKnowInAdvance";
var methodInfo = concreteType.GetMethodInfo(methodName);
var funcType = typeof(Func<>).MakeGenericType(concreteType);
var func = Delegate.CreateDelegate(funcType, methodInfo)

这将创建正确类型的委托,引用正确的方法...但是编译时类型仍然是Delegate

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44595231

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档