使用Automapper将ExpandoObject转换为抽象对象

时间:2017-03-31 03:41:08

标签: c# automapper expandoobject

样本类:

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;

再次更新......

识别TestClass

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;
    }
}

1 个答案:

答案 0 :(得分:1)

请参阅MSDN article抽象类。

对你来说重要的是:

  

无法实例化抽象类。

您需要映射到其中一个派生类,或从基类中删除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);