2013-09-24 3 views
2

Я хочу написать общую функцию, которая принимает объект и ряд свойств этого объекта. Внутри функции я хотел бы выбрать новый анонимный объект, который просто просто те свойства переданного объекта.Общая функция, которая принимает свойства как параметры

Я хочу сделать что-то вроде этого:

pubic class SimpleClass 
{ 
    public DateTime ADate {get; set;} 
    public string StringHere {get; set;} 
    public int ANumber {get; set;} 
} 

var testObj = new SimpleClass(); 
//set values here on testObj properties 
DoStuffHere(testObj, StringHere, ANumber); 

Я мог бы пройти в свойствах как строки, а затем использовать отражение, чтобы получить свойство от переданного в объекте, но я хотел бы знать, есть ли какое-то путь, который я мог бы передать в свойствах, поэтому я мог бы проверить intellisense и компилировать время, чтобы предотвратить неправильные имена свойств. Я хотел бы, чтобы моя функция getNewClass принимала любой тип объекта и, таким образом, была общей.

Редактировать: Я не возвращаю новый анонимный тип. Я думаю, что название моей функции звучит так. Я собираюсь выбрать новый анонимный тип внутри из списка указанного testObj и генерировать PDF из этих свойств.

+0

wow возвращает анонимный тип. это выглядит сложным .. возможно, выпекание какого-то ИЛ; с другой стороны, вы можете вернуть словарь <имя свойства>, значение свойства> –

+0

Если вы не имеете в виду для 'getNewClass' для * возврата * объекта, то я, возможно, неправильно понял вопрос; Я добавил во второй части свой ответ –

ответ

4

Определение анонимного типа на самом деле очень сложно, и попытка сделать это просто с именами является несколько сложной задачей. По существу то, что вы хотите, уже существует, но в обычном C# - так что для одного объекта:

var obj = new { testObj.StringHere, testObj.ANumber }; 

Или для нескольких объектов:

var projection = from obj in sequence 
       select new { obj.StringHere, obj.ANumber }; 

Это примерно так же, как сжатое вы получите. Вы можете добавить общий метод, который взял Func<,>, но он не был бы чище, чем выше.

Это не полезно иметь:

var obj = SomeMagicMethod(obj, "StringHere", "ANumber"); 

потому SomeMagicMethod мог только полезно вернуться object - наша obj переменная будет в основном непригодным для использования.


Если вам не нужно возврата объекта из метода, то вы можете использовать любой из:

SomeMagicMethod<T>(T value) { 
    ... 
} 
... 
SomeMagicMethod(new {testObj.StringHere, testObj.ANumber }); 

или:

SomeMagicMethod<TFrom, TTo>(TFrom value, Func<TFrom, TTo> selector) 
{ 
    TTo actualVal = selector(value); 
    ... 
} 
... 
SomeMagicMethod(testObj, x => new {x.StringHere, x.ANumber }); 

Лично я думаю, первое проще - функция во втором - избыток.

Вы также можете просто использовать отражение ...

SomeMagicMethod(object obj, params string[] names) 
{ 
    foreach(var name in names) { 
     object val = obj.GetType().GetProperty(name).GetValue(obj); 
     // ... 
    } 
} 
//... 
SomeMagicMethod(testObj, "StringHere", "ANumber"); 
+1

'obj' может быть' dynamic', но все же не так полезен, как обычный анонимный тип, потому что вы не получите intellisense на результат. –

+0

Он мог бы использовать динамический, но вы потеряете безопасность типа, чтобы не отвечать тоже –

+0

Я сделал редактирование на свой вопрос. Я не хочу возвращать анонимный тип. – Justin

0

вы можете передать их в качестве лямбда:

GetNewClass (testObj,()=>StringHere,()=> ANumber); 

и имеют подписи для GetNewClass как

void GetNewClass (object, Expression<Func<object>> expr0, Expression<Func<object>> expr1); 

Вы можете то получить свойство довольно легко.

+1

И что бы вернуть GetNewClass, полезный для вызывающего? Он, безусловно, не может вернуть аккуратно упакованный анонимный тип с правильно напечатанными строками 'string StringHere' и' int ANumber' ... –

+0

Вопрос не в том, как работает GetNewClass, но об переданных аргументах –

+0

Он будет возвращать поток байтов представляя сгенерированный PDF-файл, поэтому я не очень обеспокоен этим. – Justin

0

Вы можете использовать выражения Linq для этого.

(примечание: это возможно вам нужно изменить несколько вещей в приведенном ниже фрагменте кода, это в верхней части моей шляпы):

public void getNewClass(Object testObj, params MemberExpression Fields[]) 
{ 
    foreach(MemberExpression field in Fields) 
    { 
     // Get the name 
     var name = field.Member.Name; 

     // get the value 
     var member= Expression.Convert(field, typeof(object)); 
     var lambda= Expression.Lambda<Func<object>>(member); 
     var fnc= lambda.Compile(); 

     var value = fnc(); 
    } 
} 

Этот фрагмент кода показывает, как получить имя свойства и Значение. Его можно назвать следующим образом:

getClass(someObj, obj => obj.SomeProperty, obj.SomeOtherProperty); 
Смежные вопросы