繁体   English   中英

Type.GetMethod() 用于多态方法(泛型和非泛型)

[英]Type.GetMethod() for polymorphic method (both generic and non-generic)

我目前正在创建一种自定义方式来深度复制我的对象。 我使用 static class 来实现此功能。

public static class CopyServer
{

    public static int CopyDeep(int original)
    {
        return original;
    }
    //not shown: same for all other value types I use (long, float,...)


    public static T CopyDeep<T>(T original) where T: ICopyAble
    {
        if (original == null)
            return default;
        if (original is ICopyAutofields)
            return CopyAutofields(original);
        return (T)original.CopyDeep();
    }

    private static T CopyAutofields<T>(T original)
    {
        Delegate del;
        if (!_copyFunctions.TryGetValue(typeof(T), out del))
        {
            //not shown: Building expression for parameter etc.
            foreach (var fieldInfo in typeof(T).GetFields())
            {
                //not shown: checking options set by custom attributes

                MethodInfo methodInfo = typeof(CopyServer).GetMethod("CopyDeep", new[] { fieldInfo.FieldType });
                //I can't remove the second param without getting an AmbiguousMatchException

                if (methodInfo == null)
                {
                    throw new Exception($"CopyDeep not defined for type {fieldInfo.FieldType}");
                }

                if (methodInfo.IsGenericMethod)
                    methodInfo = methodInfo.MakeGenericMethod(fieldInfo.FieldType);

                Expression call = Expression.Call(methodInfo, readValue);

                //not shown: Assign Expression

            }

            //not shown: return Expression and compiling
        }
        return ((Func<T, T>)del)(original);
    }
}

我使用T CopyAutofields<T>来构建函数(通过构建和编译表达式树),因此我不必为要手动复制的每个 class 创建复制函数。 我使用自定义属性控制复制行为(我将这部分留在上面的代码中,因为它与我的问题无关)。

只要仅使用存在非泛型 function 类型的字段,该代码就可以正常工作。 但它无法检索我的通用 function T CopyDeep<T>

例子:

//This works:
public class Manager : ICopyAble,ICopyAutofields
{
    public string FirstName;
    public string LastName;
}

//This doesn't
//Meaning: typeof(CopyServer).GetMethod("copyDeep", new[] { fieldInfo.FieldType }); 
//in T copyAutofields<T> returns null for the Manager-field and my exception gets thrown
public class Employee : ICopyAble,ICopyAutofields
{
    public string FirstName;
    public string LastName;
    public Manager Manager;
}

//This is what I was using before I started using the ICopyAutofields. 
//This approach works, but its' too much too write since my classes usually 
//have way more than three fields and I occasionally forget to update 
//copyDeep()-function if I add new ones.
public class Employee : ICopyAble,ICopyAutofields
{
    public string FirstName;
    public string LastName;
    public Manager Manager;

    public IModable CopyDeep()
    {
        var result = new Employee();
        result.FirstName = CopyServer.copyDeep(FirstName);
        result.LastName= CopyServer.copyDeep(LastName);
        result.Manager= CopyServer.copyDeep(Manager);
        return result;
    }
}

长话短说:如果具有正确名称的泛型和非泛型函数都存在,我需要一种为类型 T 获取匹配的 function 的方法。

在 .NET 4.7.1 中,您需要使用方法GetMethods并过滤结果:

class MyClass
{
    public T M<T>(T t) { return default(T); }
    public int M(int t) { return 0; }
}

var m = typeof(MyClass).GetMethod("M", new[] { typeof(string) }); // null
var m1 = typeof(MyClass).GetMethods()
    .Where(mi => mi.Name == "M" && mi.GetGenericArguments().Any())
    .First(); // returns generic method

在 .NET 标准 2.1(和 .NET 核心自 2.1 起)中,还有另一种解决泛型类型 arguments - Type.MakeGenericMethodParameter的方法,就像您在此答案中看到的那样。

作为解决方法,您可以将copyAutofields<T>方法移动到通用 class ,例如CopyAutoFieldServer<T>

public static class CopyAutoFieldServer<T>
{
    public static T copyAutofields(T original) { ... }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM