使用Action委托根据泛型类型调用正确的函数

时间:2013-02-12 15:11:03

标签: c# generics delegates action func

我之前看过这种模式/方法,我正在尝试重新创建它以使我现有的一些代码更有效率。

用例: 从源系统检索复杂对象。客户端将只使用一部分信息,因此我们必须将此复杂对象“映射”为一个简单的POCO以进行JSON序列化;另外,在该映射方法中,完成了一些其他数据格式化。首先,我们将复杂对象传递给执行一些基本处理的通用方法

// Generic Method, Entry Point for mapping
static void GenericEntry<T, TK>(string userid, string environment, DBContext context) {

    .... // do stuff with userid and environment to set a context
    .... // query results, which return a complex object of Type TK

    // Here is where I would like to use an Action delegate to call the appropriate map
    // method.. there could hundreds of objects that map and process down to a POCO, 
    // Currently, this logic is using reflection to find the appropriate method with 
    // the appropriate signature... something like: 
    Type functionType = typeof(DTOFunctions);
    var methods = functionType.GetMethods(BindingFlags.Public | BindingFlags.Static);
    var mi = methods.FirstOrDefault(x => x.Name == "MapObject" && 
        x.ReturnType == typeof(T));

    if (mi == null) throw new ArgumentException(string.Format("Unable to find method MapObject for {0}", typeof(TK).Name));

    var resultList = new ArrayList();
    foreach (var row in results)
    {
        var poco = mi.Invoke(functionType, new object[] { row });
        resultList.Add(poco);
    }
    if (resultCount == -1) resultCount = resultList.Count;
    return SerializeDTO(resultList, ResponseDataTypes.JSON, resultCount);

    // THERE HAS TO BE A BETTER WAY STACKOVERFLOW! HALP!
} 

public Class DTOFunctions {
    // Mapping Method from Complex to Simple object
    static SimplePOCO_A MapObject(ComplexObject_A cmplx){
        var poco = new SimplePOCO_A(); 
        .... // mapping from cmplx field to SimplePOCO field
    }

    static SimplePOCO_B MapObject(ComplexObject_B cmplx) {
        var poco = new SimplePOCO_B(); 
        .... // mapping from cmplx field to SimplePOCO fiel
    }
}

2 个答案:

答案 0 :(得分:2)

我不太确定你在问什么,但是你想要的是什么?

static void GenericEntry<T, TK>(string userid, string environment, 
                                DBContext context, Func<T, TK> conversion) 
{
    //....
    var resultList = new List<TK>();
    foreach (var row in results)
    {
        var poco = conversion(row);
        resultList.Add(poco);
    }
    //....
}

被称为:

 GenericEntry<ComplexObject, SimplePOCO>(userid, environment, context, DTOFunctions.MapObject)

(请注意参数中缺少()。)

答案 1 :(得分:0)

看起来你可以在这里实现Proxy Pattern。 否则,可能将逻辑移动到实际对象本身,并在每个知道如何序列化自身的ComplexObject中添加ToJSON()方法。然后将它们附加在一起以生成JSON数组。这将取决于您用于序列化JSON的内容,因此在下面的示例中,我刚刚手动完成。

常见的JSONSerializable接口

    public interface IJsonSerializable
    {
        string ToJson();
    }

复杂和简单的对象:

    public class ComplexObjectA : IJsonSerializable
    {
        public string ToJson()
        {
            var simpleObject = new SimpleObjectA();

            // Map away

            // Then serialize
            return SerializeDTO(simpleObject);
        }

        private string SerializeDTO(SimpleObjectA simpleObject)
        {
            throw new NotImplementedException();
        }
    }

    public class SimpleObjectA
    {
        // simple properties
    }

然后是切入点

        static void GenericEntry<T, TK>(string userid, string environment, DBContext context)
        {

            // Magic happens here
            var results = GetResults();

            // More magic

            var resultList = new List<string>();
            foreach (var row in results)
            {
                var poco = row.ToJson();
                resultList.Add(poco);
            }
            return String.Format("[{0}]", String.Join(resultList, ", "));
        }