【问题标题】:cast to a variable type转换为变量类型
【发布时间】:2013-03-21 16:32:14
【问题描述】:

是否可以从 Dynamic 或 Object 转换为变量类型?目标变量类型是一个泛型类,只是具体数据类型不同。

我正在寻找抽象的解决方案,但情况是这样的:我想要一个针对不同实体的 Linq2SQL 命令 - 我可以 GetProperty + GetValue 的 EntityFramework 上下文,但是必须将它转换为一些确切的类型,但是这些来自变量输入 - 数据库表的名称。

我所拥有的示例:

 Type NewType = typeof(System.Data.Objects.ObjectSet<>);
 NewType.MakeGenericType(new Type[] {"...some type here that's variable accordint to user input - like Person, Address, Contact, ..."});            
 Object MyObject = Context.GetType().GetProperty("the same variable like above - Person, Address,...", BindingFlags.Public | BindingFlags.Instance).GetValue(Context, null); // this is EntityFramework Context

我需要但不知道怎么做的例子:

 NewType CastedObject = (NewType) MyObject;
 // or
 NewType CastedObject = Convert.ChangeType(MyObject, NewType);
 // or
 NewType CastedObject = MyObject as NewType;

所以我可以这样做:

 (from x in CastedObject where x.ID == ID select x).FirstOrDefault();

对于那些熟悉 PHP 的人,我正在尝试这样做:

 (from x in Context.$tablename where x.ID == ID select x).FirstOrDefault();

【问题讨论】:

标签: c# dynamic reflection


【解决方案1】:

既然NewType 是一个运行时类型,你怎么会有一个编译时类型NewType 的变量呢?编译器必须知道所有变量的“声明”类型。所以你想要的都是不可能的。

可以做的事情是将MyObject 转换为dynamic。然后像foreach (var x in CastedToDynamic) 这样的东西会编译(但没有编译时类型检查)。

但是,您不能在 dynamic 表达式上使用 LINQ。您将不得不像这样重写:

    dynamic found = null;
    foreach (var x in CastedToDynamic)
    {
      if (x.ID == ID)
      {
        found = x;
        break;
      }
    }

注意:使用== 的哪个重载将在运行时决定。因此,即使ID 是(装箱的)System.Guid,例如,== 将(取消装箱并)调用该结构内定义的== 的重载。所以这行得通。

【讨论】:

  • 即使在 EF 中声明了 NewType,但只是由变量“动态选择”?
  • 这个主意不错,我明天试试,谢谢
  • @JanMatousek(您的第一条评论)您不可能声明“非固定”类型的变量。你得到的最接近的是泛型类型。但是当您从“用户输入”构造类型时,它无济于事。泛型类型仍然是编译时类型,例如 void MyMethod&lt;T&gt;(T arg) { ... } 类型 T 绑定编译时。所以没有运气。
  • 此解决方案有效! foreach(var x in (dynamic)CastedObject) {...} 谢谢
【解决方案2】:

这样的事情可能会得到你正在看的东西(很大程度上依赖于反射)

        List<dynamic> mylist = new List<dynamic>();
        dynamic data = new ExpandoObject();
        data.Foo = "foo";
        data.ID = 1;
        mylist.Add(data);

        data = new ExpandoObject();
        data.Foo = "foobar";
        data.ID = 2;
        mylist.Add(data);


        data = new ExpandoObject();
        data.Foo = "foobar2";
        data.ID = 2;
        mylist.Add(data);

        data = new ExpandoObject();
        data.Foo = "foobar2";
        data.ID = 3;
        mylist.Add(data);

        int idiminterestedin = 2;

        var dynamicselected = mylist.Select(d=>((IDictionary<string,object>)d)).Where(d=>
        {
            object id;
            if (d.TryGetValue("ID",out id))
            {
                return (id is int) && (int)id == idiminterestedin;
            }
            return false;
        });

        foreach (var v in dynamicselected)
        {
            Console.WriteLine(v["Foo"]);
        }

        Console.ReadLine();

虽然我可能会跳过 ExpandoObject 并直接查找字典:

        Dictionary<string, object> data = new Dictionary<string, object>();
        data["Foo"] = "foo";
        data["ID"] = 1;

然后做一个通用的扩展函数:

static class ExptensionFunction
{
    static T GetValueAs<T>(this Dictionary<string, object> obj, string key)
    {
        return (T)obj[key];
    }

    static bool TryGetValueAs<T>(this Dictionary<string, object> d, string key, out T value)
    {
        object id;
        if (d.TryGetValue(key, out id))
        {
            if (id is T)
            {
                value = (T)id;
                return true;
            }
        }

        value = default(T);
        return false;
    }

    static IEnumerable<Dictionary<string, object>> GetValuesWithKey<T>(this List<Dictionary<string, object>> list, string key, T value)
    {
        return list.Where(d =>
        {
            T id;
            if (d.TryGetValueAs<T>(key, out id))
            {
                return id.Equals(value);
            }
            return false;
        });
    }
}

受此启发:

Creating an anonymous type dynamically?

Add property to anonymous type after creation

【讨论】:

    猜你喜欢
    • 2011-07-03
    • 2017-09-20
    • 2022-01-23
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 2011-09-13
    • 2020-10-25
    • 2020-02-01
    相关资源
    最近更新 更多