簡體   English   中英

使用Automapper將ExpandoObject轉換為抽象對象

[英]Convert ExpandoObject to abstract object using Automapper

樣本類別:

public abstract class SomeBase
{
    protected int _x = 100;
    public abstract int X { get; }
    protected int _y = 200;
    public abstract int Y { get; }
}

public class SomeBody : SomeBase
{
    public override int X { get { return _x + 10; } }

    public override int Y { get { return _y + 20; } }
    private int _z = 300;
    public int Z { get { return _z + 30; } }
}

public class SomeOne : SomeBase
{
    public override int X { get { return _x - 10; } }

    public override int Y { get { return _y - 20; } }
    private int _a = 300;
    public int A { get { return _a - 30; } }
}

對象到ExpandoObject方法:

public static ExpandoObject ToExpandoObject<T>(this T target)
{
    var jsonSerializerSettings = new JsonSerializerSettings();
    jsonSerializerSettings.Converters.Add(new StringEnumConverter());

    var json = JsonConvert.SerializeObject(target, Formatting.Indented, jsonSerializerSettings);
    var expandoObject = JsonConvert.DeserializeObject<ExpandoObject>(json, new ExpandoObjectConverter());

    return expandoObject;
}

將ExpandoObject轉換為抽象對象:

//someBase
//X = 110, Y = 220, Z = 330
SomeBase someBase = new SomeBody();
//someOne
//X = 90, Y = 180, A = 270
dynamic someOne = new SomeOne().ToExpandoObject();

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<SomeBase, SomeBase>();
});
//I want
//someBase
//X = 90, Y = 180, A = 270
Mapper.Map<ExpandoObject, SomeBase>(someOne, someBase);

但是會發生錯誤。

無法創建抽象類的實例

我們如何處理這個問題?

AutoMapper版本為6.02

*由於英語不成熟,請考慮使用Google翻譯器。

更新:

我知道抽象。

我只想知道AutoMapper是否可以執行以下操作:

SomeBody someBody = new SomeBody();
//someBase
//X = 110, Y = 220, Z = 330
SomeBase someBase = someBody;
SomeOne someOne = new SomeOne();
//someBase
//X = 90, Y = 180, A = 270
someBase = someOne;

再次更新...

測試類

public class TestClass
{
    public int IntValue { get; set; }
    public SomeBase SomeBase { get; set; }
}

我的最終目標是:

var testClass = new TestClass();
testClass.IntValue = 10;
testClass.SomeBase = new SomeBody();

dynamic expandoObject = testClass.ToExpandoObject();
expandoObject.SomeBase = new SomeOne().ToExpandoObject();

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<TestClass, TestClass>();
});
///Mapping the expandoObject object that changed the property to the testClass object again
///My expectation is that the type of SomeBase Property in testClass is SomeOne.
Mapper.Map<ExpandoObject, TestClass>(expandoObject, testClass);

非常感謝您用不足的英語和不足的幫助來幫助我。

我的解決方案

var testClass = new TestClass();
testClass.IntValue = 10;
testClass.SomeBase = new SomeBody();

dynamic expandoObject = testClass.ToExpandoObject();
expandoObject.SomeBase = new SomeOne().ToExpandoObject();

Mapper.Initialize(cfg =>
{
    cfg.CreateMap<ExpandoObject, SomeBase>().ConvertUsing(new SomeBaseConverter());
    cfg.CreateMap<FirstItem, FirstItem>();
});

Mapper.Map<ExpandoObject, TestClass>(expandoObject, testClass);

Debug.WriteLine(testClass.SomeBase.GetType().ToString());
///"Sample.Common.Models.SomeOne"

SomeBaseConverter:

public class SomeBaseConverter : ITypeConverter<object, SomeBase>
{
    public SomeBase Convert(dynamic source, SomeBase destination, ResolutionContext context)
    {
        var dictionary = source as IDictionary<string, object>;

        if (dictionary.ContainsKey("Z"))
        {
            var someBody = new SomeBody();

            var config = new MapperConfiguration(cfg => cfg.CreateMap<ExpandoObject, SomeBody>());
            config.CreateMapper().Map(source, someBody);

            destination = someBody;
        }
        else
        {
            var someOne = new SomeOne();

            var config = new MapperConfiguration(cfg => cfg.CreateMap<ExpandoObject, SomeOne>());
            config.CreateMapper().Map(source, someOne);

            destination = someOne;
        }

        return destination;
    }
}

請參閱MSDN文章重新抽象類。

對您來說重要的部分是:

抽象類無法實例化。

您需要映射到派生類之一,或者從基類中刪除abstract修飾符。

如果您有靜態類型的對象,則AutoMapper非常有用。 它很好地處理了多態:

Mapper.CreateMap<SomeBase1, SomeBase2>()
    .Include<SomeBody1, SomeBody2>()
    .Include<SomeOne1, SomeOne2>();

Mapper.CreateMap<SomeBody1, SomeBody2>();
Mapper.CreateMap<SomeOne1, SomeOne2>();

// for a single object:

SomeBase1 source = GetDatum();
SomeBase2 = Mapper.Map<SomeBase1, SomeBase2>();

// for an IEnumerable:

IEnumerable<SomeBase1> source = GetData();
IEnumerable<SomeBase2> = Mapper.Map<IEnumerable<SomeBase1>, IEnumerable<SomeBase2>>(source);

但是您正在使用ExpandoObject,因此更加困難。 如果您可以通過ExpandoObject中的數據來區分所需的類,則可以嘗試如下操作:

Mapper.CreateMap<ExpandoObject, SomeBase>()
    .ConstructUsing((ExpandoObject input) => {
        if (input.X == 5)
        {
            return new SomeOne();
        }
        else
        {
            return new SomeBody();
        }
    });

然后在Mapper.Map<Expandoobject, SomeBase>(...)起作用之前使用的代碼。 否則,您可以專門告訴它要映射到的類型: Mapper.DynamicMap<SomeBody>(someOne);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM