1

Linq クエリの結果からクラス インスタンスを作成しようとしています。多くのクラスでこれを行う必要があるため、最適なショートカットを見つけようとしています。クエリの「選択」部分を短くできないかどうか疑問に思っています。

私のクラス:

public class current_control_id_class
{
    public string asset_class { get; set; }
    public string region_code { get; set; }
    public string instance_code { get; set; }
    public int sdi_control_id { get; set; }
    public int rows_loaded { get; set; }  
}

私の割り当て機能:

foreach (var results in query)
{
    foreach (PropertyInfo result in results.GetType().GetProperties())
    {
        string name = result.Name;

        foreach (PropertyInfo info in used.GetType().GetProperties())
        {
            if (result.Name == info.Name)
            {
                Console.WriteLine("Result {0} matches class {1} and the value is {2}", result.Name, info.Name, result.GetValue(results,null));
            }                        
        }
    }
}

私のクエリ(私はこれが機能することを知っています)

current_control_id_class used = new current_control_id_class();

var query =
    from result in t_sdi_current_control_id.AsQueryable()
    where result.asset_class == asset_class
    && result.region_code == region
    && result.instance_code == site
    select new current_control_id_class() { 
        rows_loaded = result.rows_loaded,
        sdi_control_id = result.sdi_control_id,
        asset_class = result.asset_class,
        hsbc_region_code = result.hsbc_region_code,
        hsbc_instance_code = result.hsbc_instance_code
    };
4

2 に答える 2

2

AutoMapperを使用して のt_sdi_current_control_idインスタンスを のインスタンスにマップできる場合がありcurrent_control_id_classます。

最初にマッピングを初期化します。

Mapper.CreateMap<t_sdi_current_control_id, current_control_id_class>();

次に、それを使用します。

var query =
    from result in t_sdi_current_control_id.AsQueryable()
    where result.asset_class == asset_class
    && result.region_code == region
    && result.instance_code == site
    select Mapper.Map<current_control_id_class>(result);
于 2013-09-13T08:28:49.580 に答える
0

サードパーティのライブラリを使用したくない場合は、次のテスト済みコードを使用してください。

/// <summary>
/// Maps instances of <typeparam name="TSource"/> to new instances of
/// <typeparam name="TDestination"/> by copying across accessible public
/// instance properties whose names match.
/// </summary>
/// <remarks>
/// Internally uses a compiled Expression, so mapping should be quick at
/// the expense of <see cref="Mapper"/> initialisation.
/// </remarks>
public class Mapper<TSource, TDestination>
    where TDestination : new()
{
    readonly Func<TSource, TDestination> map;

    public Mapper()
    {
        this.map = GenerateMapping();
    }

    static Func<TSource, TDestination> GenerateMapping()
    {
        var sourceProperties = GetPublicInstancePropertiesWithAccessors<TSource>(property => property.GetGetMethod());
        var destinationProperties = GetPublicInstancePropertiesWithAccessors<TDestination>(property => property.GetSetMethod());

        var source = Expression.Parameter(typeof(TSource));
        var destination = Expression.Variable(typeof(TDestination));

        var copyPropertyValues = from sourceProperty in sourceProperties
                                 from destinationProperty in destinationProperties
                                 where sourceProperty.Name.Equals(destinationProperty.Name, StringComparison.Ordinal)
                                 select Expression.Assign(
                                     Expression.Property(destination, destinationProperty),
                                     Expression.Property(source, sourceProperty)
                                 );

        var variables = new[] { destination };
        var assignNewDestinationInstance = Expression.Assign(destination, Expression.New(typeof(TDestination)));
        var returnDestinationInstance = new Expression[] { destination };
        var statements =
            new[] { assignNewDestinationInstance }
            .Concat(copyPropertyValues)
            .Concat(returnDestinationInstance);
        var body = Expression.Block(variables, statements);
        var parameters = new[] { source };
        var method = Expression.Lambda<Func<TSource, TDestination>>(body, parameters);

        return method.Compile();
    }

    /// <summary>
    /// Gets public instance properties of <typeparamref name="T"/> that
    /// have accessible accessors defined by <paramref name="getAccessor"/>.
    /// </summary>
    static IEnumerable<PropertyInfo> GetPublicInstancePropertiesWithAccessors<T>(Func<PropertyInfo, MethodInfo> getAccessor)
    {
        var type = typeof(T);
        var publicInstanceProperties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
        return from property in publicInstanceProperties
               let accessor = getAccessor(property)
               where accessor != null
               select property;
    }

    public TDestination Map(TSource source)
    {
        return map(source);
    }
}

次のように使用します。

//Keep this around so it gets re-used.
var mapper = new Mapper<t_sdi_current_control_id, current_control_id_class>();

var result = mapper.Map(value);
于 2013-09-13T12:06:27.580 に答える