C# 用于将简单实体属性自动映射到SqlParameters数组

C# 用于将简单实体属性自动映射到SqlParameters数组,c#,automapper,C#,Automapper,我已经开始研究AutoMapper,有一个“数据驱动”的场景。。。我有根据我传递的一些“模式信息”从SqlDataReader填充实体属性的代码 下一步我想拿实体属性。。。然后根据我掌握的模式信息,从实体值创建一组SqlParameters 汽车制造商的完美工作。。。但我看到很多从对象图到对象图的扁平化,但没有简单的示例用于此任务。。。当我开始做这件事的时候,我有点被一些细微的差别绊倒了,但是我对我应该做什么有一个粗略的想法 我起草了以下文件。。。我试图使用类型转换器并提前注册它们,但当我执行实

我已经开始研究AutoMapper,有一个“数据驱动”的场景。。。我有根据我传递的一些“模式信息”从SqlDataReader填充实体属性的代码

下一步我想拿实体属性。。。然后根据我掌握的模式信息,从实体值创建一组SqlParameters

汽车制造商的完美工作。。。但我看到很多从对象图到对象图的扁平化,但没有简单的示例用于此任务。。。当我开始做这件事的时候,我有点被一些细微的差别绊倒了,但是我对我应该做什么有一个粗略的想法

我起草了以下文件。。。我试图使用类型转换器并提前注册它们,但当我执行实际的map.ForMember()操作时,它会抛出一个错误

“成员的自定义配置仅支持类型上的顶级单个成员。”

我尝试过一些变体,但没有成功

(1) 尝试了更简单的版本。。。 (2) 尝试使用ConstructUsing()机制,然后操作的目标实际上是SqlParameter。[[[Value]]]属性(很可能是AutoMapper思维方式中的“正确”方式对吗??) (3) 尝试预先建立目标列表,然后“查找”匹配参数-但设置其上的.Value仍然是等式中缺少的一部分

作为汽车制造商的新手,我期待着一些挑战,但我在这方面花了足够的时间,并没有发现任何明显的。。。似乎它应该是一个简单的框架用例。。。我一定错过了什么明显的

class Program
{
    static void Main(string[] args)
    {
        // Drive it by some data... Say some mapping info we have from elsewhere...
        var myMappingPairs = new List<MyMappingInfo>()
        {
            new MyMappingInfo() { PropertyName = "MyGuidProperty", ParameterName = "Param00" },
            new MyMappingInfo() { PropertyName = "MyStringProperty", ParameterName = "Param01" },
            new MyMappingInfo() { PropertyName = "MyInt16Property", ParameterName = "Param02" },
            new MyMappingInfo() { PropertyName = "MyInt32Property", ParameterName = "Param03" },
            new MyMappingInfo() { PropertyName = "MyInt64Property", ParameterName = "Param04" }
        };

        // We can try to register these, but the sytax isn't clear to me yet...
        Mapper.CreateMap<Guid, SqlParameter>().ConvertUsing<GuidToSqlParameterConverter>();
        Mapper.CreateMap<String, SqlParameter>().ConvertUsing<StringToSqlParameterConverter>();
        Mapper.CreateMap<Int16, SqlParameter>().ConvertUsing<Int16ToSqlParameterConverter>();
        Mapper.CreateMap<Int32, SqlParameter>().ConvertUsing<Int32ToSqlParameterConverter>();
        Mapper.CreateMap<Int64, SqlParameter>().ConvertUsing<Int64ToSqlParameterConverter>();

        // Next we'll build our mapping from the "pairings"...
        var map = Mapper.CreateMap<MySourceEntity, List<SqlParameter>>();

        foreach (var mappingPair in myMappingPairs)
        {
            map.ForMember
                (
                    destination => destination,
                    options => options.ResolveUsing<PropertyNameResolver>().FromMember
                        (
                            mappingPair.PropertyName    // <-- Data Driven Property Name...
                        )
                );
        }

        // Create a test entity...
        var entity = new MySourceEntity() 
        {
            MyGuidProperty = Guid.NewGuid(), 
            MyStringProperty = "Hello AutoMapper",
            MyInt16Property = Int16.MaxValue,
            MyInt32Property = Int32.MaxValue,
            MyInt64Property = Int64.MaxValue
        };

        // Map it...
        var values = Mapper.Map<MySourceEntity, object[]>
            (
                entity
            );

    }
}

public class MySourceEntity
{
    public string MyStringProperty { get; set; }
    public DateTime? MyDateTimeProperty { get; set; }
    public Byte? MyByteProperty { get; set; }
    public Int16? MyInt16Property { get; set; }
    public Int32? MyInt32Property { get; set; }
    public Int64? MyInt64Property { get; set; }
    public Guid? MyGuidProperty { get; set; }

    public List<String> ThisShouldntGetMapped { get; set; }
    public StringBuilder NorShouldThis { get; set; }
}

public class MyMappingInfo
{
    public String PropertyName { get; set; }
    public String ParameterName { get; set; }
    public SqlDbType SqlDbType { get; set; }
}

public class GuidToSqlParameterConverter : AutoMapper.ITypeConverter<Guid, SqlParameter>
{
    public SqlParameter Convert(ResolutionContext context)
    {
        if (context.IsSourceValueNull)
        {
            return new SqlParameter()
            {
                ParameterName = "GuidParam",
                SqlDbType = SqlDbType.UniqueIdentifier,
                Value = DBNull.Value
            };
        }
        else
        {
            return new SqlParameter()
            {
                ParameterName = "GuidParam",
                SqlDbType = SqlDbType.UniqueIdentifier,
                Value = context.SourceValue
            };
        }
    }
}
public class StringToSqlParameterConverter : AutoMapper.ITypeConverter<string, SqlParameter>
{
    public SqlParameter Convert(ResolutionContext context)
    {
        if (context.IsSourceValueNull)
        {
            return new SqlParameter()
            {
                ParameterName = "StringParam",
                SqlDbType = SqlDbType.NVarChar,
                Value = DBNull.Value
            };
        }
        else
        {
            return new SqlParameter()
            {
                ParameterName = "StringParam",
                SqlDbType = SqlDbType.NVarChar,
                Value = context.SourceValue
            };
        }
    }
}

public class Int16ToSqlParameterConverter : AutoMapper.ITypeConverter<Int16, SqlParameter>
{
    public SqlParameter Convert(ResolutionContext context)
    {
        if (context.IsSourceValueNull)
        {
            return new SqlParameter()
            {
                ParameterName = "Int16Param",
                SqlDbType = SqlDbType.SmallInt,
                Value = DBNull.Value
            };
        }
        else
        {
            return new SqlParameter()
            {
                ParameterName = "Int16Param",
                SqlDbType = SqlDbType.SmallInt,
                Value = context.SourceValue
            };
        }
    }
}

public class Int32ToSqlParameterConverter : AutoMapper.ITypeConverter<Int32, SqlParameter>
{
    public SqlParameter Convert(ResolutionContext context)
    {
        if (context.IsSourceValueNull)
        {
            return new SqlParameter()
            {
                ParameterName = "Int32Param",
                SqlDbType = SqlDbType.Int,
                Value = DBNull.Value
            };
        }
        else
        {
            return new SqlParameter()
            {
                ParameterName = "Int32Param",
                SqlDbType = SqlDbType.Int,
                Value = context.SourceValue
            };
        }
    }
}

public class Int64ToSqlParameterConverter : AutoMapper.ITypeConverter<Int64, SqlParameter>
{
    public SqlParameter Convert(ResolutionContext context)
    {
        if (context.IsSourceValueNull)
        {
            return new SqlParameter()
            {
                ParameterName = "Int64Param",
                SqlDbType = SqlDbType.BigInt,
                Value = DBNull.Value
            };
        }
        else
        {
            return new SqlParameter()
            {
                ParameterName = "Int64Param",
                SqlDbType = SqlDbType.BigInt,
                Value = context.SourceValue
            };
        }
    }
}
类程序
{
静态void Main(字符串[]参数)
{
//通过一些数据驱动它…说一些我们从别处得到的映射信息。。。
var myMappingPairs=新列表()
{
新建MyMappingInfo(){PropertyName=“MyGuidProperty”,ParameterName=“Param00”},
新建MyMappingInfo(){PropertyName=“MyStringProperty”,ParameterName=“Param01”},
新建MyMappingInfo(){PropertyName=“MyInt16Property”,ParameterName=“Param02”},
新建MyMappingInfo(){PropertyName=“MyInt32Property”,ParameterName=“Param03”},
新建MyMappingInfo(){PropertyName=“MyInt64Property”,ParameterName=“Param04”}
};
//我们可以尝试注册这些,但sytax对我来说还不清楚。。。
CreateMap().ConvertUsing();
CreateMap().ConvertUsing();
CreateMap().ConvertUsing();
CreateMap().ConvertUsing();
CreateMap().ConvertUsing();
//接下来,我们将从“配对”构建映射。。。
var map=Mapper.CreateMap();
foreach(myMappingPairs中的var mappingPair)
{
map.ForMember
(
目的地=>目的地,
options=>options.ResolveUsing().FromMember
(
mappingPair.PropertyName//p.Name,
p=>p.GetValue(obj,null)??DBNull.Value);
}  

这就是对我来说使用AutoMapper的全部意义…我已经知道如何编写反射代码…我可以一直查看基于纯反射的库以获得一些额外的性能提升,但我认为AutoMapper可能是一笔两全其美的交易…

顺便说一句-最后一个代码狙击手就是从这里开始的,所以…代码到哦,太长了。你能缩小范围吗?
    static IDictionary<string, object> GetDictionaryFromObject(object obj)
    {
        if (obj == null) return new Dictionary<string, object>();
        return obj.GetType().GetProperties()
                   .ToDictionary(p => p.Name,
                                 p => p.GetValue(obj, null) ?? DBNull.Value);
    }