将ExpandoObject强制转换为匿名类型

Sen*_*ncy 12 c# generics anonymous-types expandoobject

我可以将ExpandoObject强制转换为匿名类型吗?

var anoObj = new { name = "testName", email = "testEmail" };

dynamic expandoObj = new System.Dynamic.ExpandoObject();

// Here I'm populating the expandoObj with same property names/types in anonymoustype(anoObj)

// Now, how to convert this ExpandoObject to anonymoustype ?

var newObj = (typeof(anoObj)expandoObj); // This doesn't work
Run Code Online (Sandbox Code Playgroud)

稍后添加

//这是我的实体

public class Customer
    {
        #region Public Properties

        [ColumnAttribute(Name = "IdColumn")]
        public string Id { get; set; }

        [ColumnAttribute(Name = "NameColumn")]
        public string Name { get; set; }

        [ColumnAttribute(Name = "AddressColumn")]
        public string Address { get; set; }

        [ColumnAttribute(Name = "EmailColumn")]
        public string Email { get; set; }

        [ColumnAttribute(Name = "MobileColumn")]
        public string Mobile { get; set; } 

        #endregion
    }
Run Code Online (Sandbox Code Playgroud)

// ------------------------------------------------ -------------------------------------

public class LookupService<TEntitySource>
{
    public LookupService ()
    {

    }

    public LookupShowable<TEntitySource, TSelection> Select<TSelection>(Expression<Func<TEntitySource, TSelection>> expression)
    {
        var lookupShowable = new LookupShowable<TEntitySource, TSelection>();

        return lookupShowable;
    }
}

public class LookupShowable<TEntitySource,TSelection>
{
    public LookupShowable()
    {

    }

    public LookupExecutable<TEntitySource, TSelection, TShow> Show<TShow>(Expression<Func<TEntitySource, TShow>> expression)
    {
        var lookupExecutable = new LookupExecutable<TEntitySource,TSelection,TShow>();

        return lookupExecutable;
    }
}

public class LookupExecutable<TEntitySource, TSelection, TShow>
{
    public TSelection Execute()
    {
       // Here I want to create a new instance of TSelection and populate values from database and return it.
    }
}
Run Code Online (Sandbox Code Playgroud)

// ------------------------------------------------ --------------------------------------

// This is How I want to call this from front end...
    var lookupService = new LookupService<Customer>();
    var lookupSelection = lookupService.Select(C => new { C.Id, C.Name, C.Mobile }).Show(C => new { C.Id, C.Name}).Execute();


    string sID = lookupSelection.Id;
    string sName = lookupSelection.Name;
    string sMobile = lookupSelection.Mobile;
Run Code Online (Sandbox Code Playgroud)

不要考虑这个中间部分.它的目的是另一个......

我的问题是在LookupExecutable类中的Execute()方法.我不知道如何创建TSelection类型的新实例并为其赋值.此TSelection类型始终是匿名类型.

svi*_*ick 5

编辑:我认为这个问题是XY问题的主要示例。正确的解决方案不需要关心自己ExpandoObject或匿名类型,如果这样做的话,很可能是错误的。


您正在以错误的方式看待它。您无需创建匿名对象的实例,您需要调用在表达式中传递给您的代码(可能会或可能不会创建匿名对象)。

如果你可以创建一个实例TEntitySource,那么很简单:Compile()Expression你的了Select(),然后调用它的每个实例TEntitySource

如果您无法创建TEntitySource,您仍然可以通过重写Expression(使用ExpressionVisitor)来做到这一点,以使它的输入不是TEntitySource,而是您拥有的某种类型。但这需要您的一些工作。


原始答案:

不,那行不通。这根本不是C#中强制转换或匿名类型如何工作的方式。

您不能在任何两种类型之间进行转换并期望它能正常工作。您要投射的对象需要是要投射到的类型,或者这两种类型之一需要指定匹配的投射运算符。

目标类型是匿名类型这一事实不会改变任何东西(除了您甚至不能尝试直接转换为匿名类型,因为您无法命名它;使用的方式typeof()是错误的)。

源类型是事实,这会dynamic改变一点。但是,只有在运行时而不是在编译时才完成对强制转换运算符的搜索,您甚至可以在运行时创建强制转换运算符(请参阅参考资料DynamicObject.TryCast())。就是这样,它没有添加任何“神奇的”强制转换运算符。

我可以想象这样的工作的唯一方法是,如果您使用了“示例铸造”和反射形式:

public T Convert<T>(ExpandoObject source, T example)
    where T : class
{
    IDictionary<string, object> dict = source;

    var ctor = example.GetType().GetConstructors().Single();

    var parameters = ctor.GetParameters();

    var parameterValues = parameters.Select(p => dict[p.Name]).ToArray();

    return  (T)ctor.Invoke(parameterValues);
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以像这样使用它:

var expando = new ExpandoObject();
dynamic dynamicExpando = expando;
dynamicExpando.Foo = "SomeString";
dynamicExpando.Bar = 156;
var result = Convert(expando, new { Foo = "", Bar = 1 });
Run Code Online (Sandbox Code Playgroud)

注意,您实际上不能Convert()动态地调用(通过传递dynamicExpando),因为那将意味着它也会返回dynamic


Min*_*nas 5

使用JavaScriptSerializer可以将ExpandoObject转换为以下任何类型:

.....
dynamic myExpandoObject = new ExpandoObject();
var result = ConvertDynamic<myType>(myExpandoObject);
.....


    public T ConvertDynamic<T>(IDictionary<string, object> dictionary)
    {
        var jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer();
        var obj = jsSerializer.ConvertToType<T>(dictionary);
        return obj;
    }
Run Code Online (Sandbox Code Playgroud)

这应该做的工作。

  • 这不是他所寻找的“任何类型”。特别是“到匿名类型”。 (2认同)