通用代理词典解析器< T> [英] Dictionary of generic delegate Parser<T>

查看:119
本文介绍了通用代理词典解析器< T>的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想创建一个解析器,将字符串标记转换为基于某个键的类型化对象。

I want to create a parser that convert string tokens to typed objects based on a key.

我的第一个刺,从Dictionary<T,Delegate>与不同类型的委托:清洁,非字符串方法名称?

delegate T Parser<T>(string item);

public class TableParser    
{
    static IDictionary<string, Pair<PropertyInfo, Delegate>> _PARSERS;
    static Type DOMAIN_TYPE;

    static TableParser()
    {
        DOMAIN_TYPE= typeof(Domain);

        Dictionary<string, Pair<PropertyInfo, Delegate>> parsers = new
            Dictionary<string, Pair<PropertyInfo, Delegate>>()
        {
            { "PropertyOne", new Pair<PropertyInfo,Delegate>(
                DOMAIN_TYPE.GetProperty("PropertyOne"), 
                (Parser<double>) double.Parse ) },
        };
        _PARSERS = parsers;
    }

    public List<Domain> Parse(string filename)
    {
        List<Domain> domains = new List<Domain>();

        List<List<string>> data = 
            CVSParser.Instance.Parse(filename);
        List<string> headers = data[0];

        for (int i = 1; i < data.Count; i++)
        {
            List<string> row = data[i];
        }            

        return domains;
    }

    private Dictionary<int, Pair<PropertyInfo, Delegate>> FindParsers(List<string> headers)
    {
        Dictionary<int, Pair<PropertyInfo, Delegate>> parsers =
            new Dictionary<int, Pair<PropertyInfo, Delegate>>();

        int i = 0;
        headers.ForEach(h =>
        {
            if (_PARSERS.ContainsKey(h))
            {
                parsers[i] = _PARSERS[h];
            }
            ++i;
        });

        return parsers;
    }

    private Domain Create(List<string> data,
        Dictionary<int, Pair<PropertyInfo, Delegate>> parsers)
    {
        Domain domain = new Domain();

        foreach (KeyValuePair<int, Pair<PropertyInfo, Delegate>> parser in parsers)
        {
            string datum = data[parser.Key];
            parser.Value.First.SetValue(domain,
                /* got stuck here */ parser.Value.Second,
                null);

        }

        return domain;
    }
}

我被困于重新发现解析器,当我需要使用它。我需要将它转换回 Parser< double> Parser< int> 等,具体取决于的PropertyInfo

I got stuck at re-discovering the type of the parser when I need to use it. I need to cast it back to Parser<double>, Parser<int>, etc depending on PropertyInfo.

在这种情况下,罐装CSV解析器不起作用,因为Domain的属性来自多个文件。

A canned CSV parser doesn't work in this case because Domain's properties come from multiple files.

推荐答案

虽然我可能没有完整的图片,但看起来你正在做的事情比他们需要的更复杂。

Although I may not have the full picture, it looks like you're making things more complicated than they need to be.

A在PropertyType上进行简单的切换以及直接调用适当的分析方法会使代码更易于理解和维护。如果反思成本令您担忧,请使用图书馆生成直接引用该媒体资源的代理。

A simple switch on the PropertyType and direct invocations of the appropriate parse methods would make the code simpler to understand and maintain. If the cost of reflection worries you, use a library to generate delegates that refer directly to the property.

也就是说,为了使您当前的解决方案能够工作,最简单的方法可能是使用动态调用委托:

That said, to make your current solution work, the easiest is probably to use dynamic invocation of the delegates:

parser.Value.First.SetValue(analytic, 
    parser.Value.Second.DynamicInvoke(datum),
    null);

我也忍不住提到上面引用的库提供的扩展方法,它允许您创建对象

I also cannot resist mentioning the extension methods provided by the library referenced above, which allows you to create object instances from a set of values (the data types do not need to match, types are automatically converted/coerced as needed), like this:

var properties = new [] { "One", "Two" };
var inputValues = new object[] { 1.0d, "foobar" };
var domain = typeof(Domain).TryCreateInstance( properties, inputValues );

这篇关于通用代理词典解析器&lt; T&gt;的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆