使用C#从强类型类动态构建对象?

时间:2016-07-22 09:11:09

标签: c# reflection dapper-simplecrud

目前,我正在手动添加属性和值,如此示例,并发送到Dapper.SimpleCRUD以从Dapper Orm获取数据。这是我想要实现的期望输出

object whereCriteria = null;
whereCriteria = new
{
    CountryId = 2,
    CountryName = "Anywhere on Earth",
    CountryCode = "AOE",
    IsActive = true
};

以下类应以上述格式构建对象并返回现成的对象。

public static class WhereClauseBuilder
{
    public static object BuildWhereClause(object model)
    {
        object whereObject = null;
        var properties = GetProperties(model);

        foreach (var property in properties)
        {
            var value = GetValue(property, model);

            //Want to whereObject according to the property and value. Need help in this part!!!
        }

        return whereObject;
    }

    private static object GetValue(PropertyInfo property, object model)
    {
        return property.GetValue(model);
    }

    private static IEnumerable<PropertyInfo> GetProperties(object model)
    {
        return model.GetType().GetProperties();
    }
}

此函数WhereClauseBuilder.BuildWhereClause(object model)应以预期格式(上文提及)返回对象。以下是我想要使用的实现方式。

public sealed class CountryModel
{
    public int CountryId { get; set; }
    public string CountryName { get; set; }
    public string CountryCode { get; set; }
    public bool IsActive { get; set; }
}

public class WhereClauseClass
{
    public WhereClauseClass()
    {
        var model = new CountryModel()
        {
            CountryCode = "AOE",
            CountryId = 2,
            CountryName = "Anywhere on Earth",
            IsActive = true
        };

        //Currently, won't return the correct object because the implementation is missing.
        var whereClauseObject = WhereClauseBuilder.BuildWhereClause(model);
    }
}

1 个答案:

答案 0 :(得分:1)

也许是这样的:

private const string CodeTemplate = @"
    namespace XXXX
    {
        public class Surrogate
        {
    ##code##
        }
    }";

public static Type CreateSurrogate(IEnumerable<PropertyInfo> properties)
{
    var compiler = new CSharpCodeProvider();
    var compilerParameters = new CompilerParameters { GenerateInMemory = true };
    foreach (var item in AppDomain.CurrentDomain.GetAssemblies().Where(x => !x.IsDynamic))
    {
        compilerParameters.ReferencedAssemblies.Add(item.Location);
    }

    var propertiesCode = 
        string.join("\n\n", from pi in properties
                            select "public " + pi.PropertyType.Name + " " + pi.Name + " { get; set; }");

    var source = CodeTemplate.Replace("##code##", propertiesCode);

    var compilerResult = compiler.CompileAssemblyFromSource(compilerParameters, source);
    if (compilerResult.Errors.HasErrors)
    {
        throw new InvalidOperationException(string.Format("Surrogate compilation error: {0}", string.Join("\n", compilerResult.Errors.Cast<CompilerError>())));
    }

    return compilerResult.CompiledAssembly.GetTypes().First(x => x.Name == "Surrogate");
}

现在使用它:

public static object BuildWhereClause(object model)
{
    var properties = GetProperties(model);
    var surrogateType = CreateSurrogate(properties);
    var result = Activator.CreateInstance(surrogateType);

    foreach (var property in properties)
    {
        var value = GetValue(property, model);
        var targetProperty = surrogateType.GetProperty(property.Name);
        targetProperty.SetValue(result, value, null);
    }

    return result;
}

我没有编译。它只写在这里。也许有一些错误。 : - )

编辑:

要使用ExpandoObject,您可以尝试:

public static object BuildWhereClause(object model)
{
    var properties = GetProperties(model);
    var result = (IDictionary<string, object>)new ExpandoObject();

    foreach (var property in properties)
    {
        var value = GetValue(property, model);
        result.Add(property.Name, value);
    }

    return result;
}

但我不知道这是否适合你。