簡體   English   中英

創建功能 <Type> 來自TypeInfo和MethodInfo

[英]Create Func<Type> from TypeInfo and MethodInfo

我很好奇是否有可能在僅擁有類型的同時創建委托。 像這樣:

var concreteType = DiscoverTypeInRuntime();
var methodName = "SomeNameIKnowInAdvance";
var methodInfo = concreteType.GetMethodInfo(methodName);
var dynamicallyConstructedFunc = DynamicallyConstructFunc(methodInfo)

委托應該是類型

Func<ConcreteType>

更新:

確切的類型事先未知。 它是在程序運行時發現的。 委托不能為Func<object類型,只能允許Func<ConcreteType> 已知名稱的方法是工廠方法,該方法返回ConcreteType的實例,從而返回要求。

更新2:

我將在此處提供一些代碼來解釋用例。 希望這可以澄清問題:

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。

借助Reflection,您可以構造一個功能如下:

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

這是一個示例用法:

var methodName = "SomeNameIKnowInAdvance";
var dynamicallyConstructedFunc = GetDelegateFromMethodName<ConcreteClass>(methodName);

請記住,這僅適用於靜態方法,如果您想使其也適用於實例方法,則還需要傳遞實例:

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

一個示例用法是:

var methodName = "ConstructClass";
var dynamicallyConstructedFunc = GetDelegateFromMethodName<ConcreteClass>(new ConcreteClass(), methodName);

如果您不喜歡泛型,也可以使用object但這不會導致Func<ConcreteClass>您必須手動將其強制轉換:

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

您可以創建這樣的委托-但是您只能將其稱為Delegate因為您在編譯時不知道實際的類型。 它要求使用MakeGenericTypeFunc<T>創建適當的委托類型。

var concreteType = DiscoverTypeInRuntime();
var methodName = "SomeNameIKnowInAdvance";
var methodInfo = concreteType.GetMethodInfo(methodName);
var funcType = typeof(Func<>).MakeGenericType(concreteType);
var func = Delegate.CreateDelegate(funcType, methodInfo)

這將創建正確的委托類型,並引用正確的方法...,但是編譯時類型仍然只是Delegate

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM