【问题标题】:How can i cast from Func<Object> to Func<dynamicType> c#如何从 Func<Object> 转换为 Func<dynamicType> c#
【发布时间】:2016-07-01 23:32:45
【问题描述】:

你好,这是我的第一篇文章,如果我做错了什么,请不要难过:D

我正在为一个大型程序编写反序列化器, 为此,我有一个自己的类

public class DeSerializeableElement
{
    public Func<Object> action;
    public Type type;

    public DeSerializeableElement( Func<Object> p_action,Type p_type)
    {   
        type = p_type;
        action = p_action;
    }

我读了一个字符串,然后它总是以 0XXX 一个 4 位数字开头。 有了这个数字,我可以从我的

中获得正确的方法
Dictionary<int,DeSerializableElement>

字典的初始化是自动生成的,有 300 个元素

deSerializableObjectDictionary.Add(276, new DeSerializeableElement(GetString, typeof(System.String)));

GetString 是一个没有参数的方法,返回一个字符串

现在我的问题是,如果我反序列化一个列表,那么在我创建一个 DeSerializableElement 的那一刻,Func 会丢失其返回值信息。因为我把它保存为 Func 所以我得到了一个 List 但是在 GetString 的情况下获取 List 很重要 还有 GetInt 或 GetDouble 等等

所以如果我调用 GetList(GetString) 作为返回值,我想要一个 List 如果我调用 GetList(GetInt) 我想要一个 List 等等。 但我总是得到一个列表,因为我的 SerializableElement 具有 Func 作为属性

GetList 的调用看起来像

GetList(deSerializableObjectDictionary[objectIdent].action);

GetList 看起来像

public IList<T> GetList<T>(Func<T> p_action) //T is always Object because of Func<Object> here I the right Type
{
    IList<T> list = new List<T>();
    ExpectToken('[');          //The start Token of a serialized List
    while (!IsNextToken(']'))  //End Token of serialized List
    {
        list.Add(p_action());
    }
    return lst;
}

【问题讨论】:

  • 我无法理解你的问题。您能否更明确地说明什么不起作用以及您想要做什么?
  • 所以你想为int返回一个List&lt;int&gt;,为string返回一个List&lt;string&gt;
  • 是的,这就是我想要的
  • 很怀疑这就是你想要的,抛弃类型安全几乎从来都不是一个错误,但除非你尝试过,否则你不会发现这一点。您必须使用 Delegate 或 Func&lt;dynamic&gt;
  • 无论您如何看待它,您都需要某种运行时强制转换来完成这项工作。谨慎使用。

标签: c# generics delegates


【解决方案1】:

您选择的任何道路都会使您失去字体安全性。例如,您可以遵循 Dictionary&lt;int, object&gt; 并使用 GetList&lt;T&gt; 方法包装它,其中 T 是您想要的实际类型。滥用此方法可能会导致运行时异常。

一个例子是:

void Main()
{
    var idToFunc = new Dictionary<int, object>();
    idToFunc.Add(1, new DeSerializeableElement<int>(() => 1));

    Console.WriteLine(GetList<int>(((DeSerializeableElement<int>) idToFunc[1]).Func));
}

public class DeSerializeableElement<T>
{
    public Func<T> Func { get; set; }
    public DeSerializeableElement(Func<T> func)
    {
        Func = func;
    }
}

我肯定会考虑这种代码所涉及的风险。虽然可能,但我建议您重新考虑您在做什么以及反序列化器的架构。

【讨论】:

    猜你喜欢
    • 2021-05-08
    • 1970-01-01
    • 2015-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-04
    • 1970-01-01
    相关资源
    最近更新 更多