2013-09-13 4 views
1

Я пытаюсь создать экземпляр класса из моего результата запроса Linq. Поскольку я должен делать это для многих классов, я пытаюсь найти наиболее подходящий ярлык. Мне интересно, могу ли я сделать «выбор» части запроса короче.Создание экземпляра класса из результата запроса 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 
    }; 
+0

Похоже, что вы можете использовать [AutoMapper] (http://automapper.org/). –

+0

Является ли t_sdi_current_control_id коллекцией/массивом current_control_id_class? Или имена свойств всегда совпадают между запросом и классом, который вы пытаетесь создать? –

ответ

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); 
+0

Вы можете получить automapper, используя пакет nuget .. –

+0

Спасибо! Это было бы замечательно! Однако в компании, с которой я работаю, меня бы сразу уволили за скачивание чего-либо из Интернета. Не спрашивайте .... – vwdewaal

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); 
Смежные вопросы