2012-03-08 3 views
0

Я пытаюсь выяснить что-то с кодом C#, и я не уверен на 100%, если это возможно, но я пытаюсь реализовать функции поиска для нескольких классов, которые упрощены и в целом легко развиваются. Сейчас у меня есть следующий код:Сильно типизированная функция поиска для класса?

[DataContract(IsReference = true), Serializable] 
public class ClassSearch 
{ 
    [DataMember] 
    public string Name { get; set; } 

    [DataMember] 
    public object Value { get; set; } 

    public override string ToString() 
    { 
     return String.Format("{0} = {1}", Name, Value); 
    } 

    ... // additional logic 
} 

Однако, я хотел бы включить строгую типизацию для значения объекта так, чтобы она только может быть установлена ​​на имущество, которое передается, я думаю, как и аналогичные (гипотетический, не уверен, если это будет работать)

[DataContract(IsReference = true), Serializable] 
public class ClassSearch<TProperty> 
{ 
    [DataMember] 
    public TProperty Property {get; set; } 


    public override string ToString() 
    { 
     return String.Format("{0} = '{1}'", Property.Name, Property); 
    } 

    ... // additional logic 
} 

public class MainClass 
{ 
    public void Execute() 
    { 
     SomeClass someClass = new Class{ 
      Property = "Value"; 
     }; 

     ClassSearch search = new ClassSearch<SomeClass.Property>{ 
      Property = someClass.Property 
     }; 

     var retString = search.ToString(); // Returns "Property = 'Value'" 
    } 
} 
+0

В зависимости от того, как вы планируете выставлять свою конечную точку wcf, у вас могут возникнуть проблемы с генериками, в случае, если базовыйHttpBinding не сможет обслуживать ClassSearch , а ClassSearch определяется в той же службе. –

+0

Я не понимаю, чего вы хотите получить. Вспомогательный класс, который может искать имена свойств и их значения любого класса и может их распечатать? Вы можете использовать отражение. Абстрактный класс или интерфейс 'ISearchable', который делает класс доступным для поиска? – vulkanino

+0

Извините, игнорируйте теги wcf. –

ответ

0

кажется, вы пытаетесь создать службу WCF, чтобы иметь возможность передавать любой тип вы любите.

Прежде всего, это не WSDL-friendly. Все службы WCF должны быть доступны в WSDL. WSDL - это все о четко определенных контрактах, поэтому типы должны быть определены. Таким образом, общий подход не будет работать - в основном из-за WSDL. Сказав это, вы все равно можете использовать дженерики, но тогда вам нужно использовать KnownType и на самом деле определить все возможные типы - что для меня побеждает объект.

Все, что вы можете сделать, это сериализовать объект самостоятельно и пройти его по типу по проводке. С другой стороны, вы можете подобрать десериализацию.

Так что-то вдоль линии:

// NOTE: Not meant for production! 
[DataContract] 
public class GenericWcfPayload 
{ 
    [DataMember] 
    public byte[] Payload {get; set;} 

    [DataMember] 
    public string TypeName {get; set;} 
} 
0

Если нет легче ответы, которые я хотел бы попробовать с этим.
Вы можете использовать выражения так:

// Sample object with a property. 
SomeClass someClass = new SomeClass{Property = "Value"}; 

// Create the member expression. 
Expression<Func<object /*prop owner object*/, object/*prop value*/>> e = 
    owner => ((SomeClass)owner).Property; 

// Get property name by analyzing expression. 
string propName = ((MemberExpression)e.Body).Member.Name; 

// Get property value by compiling and running expression. 
object propValue = e.Compile().Invoke(someClass); 

сдает свою собственность по выражению члена owner => ((SomeClass)owner).Property. Это выражение содержит как необходимую информацию: имя свойства и значение свойства. Последние две строки показывают, как получить имя и значение.


После увеличения например:

class MainClass 
{ 
    public static void Execute() 
    { 
    SomeClass someClass = new SomeClass{ 
     Property = "Value" 
    }; 


    var search = new ClassSearch(s => ((SomeClass)s).Property); 

    Console.Out.WriteLine("{0} = '{1}'", search.Property.Name, search.Property.GetValue(someClass)); 
    } 
} 

class Reflector 
{ 
    public static string GetPropertyName(Expression<Func<object, object>> e) 
    { 
    if (e.Body.NodeType != ExpressionType.MemberAccess) 
    { 
     throw new ArgumentException("Wrong expression!"); 
    } 

    MemberExpression me = ((MemberExpression) e.Body); 

    return me.Member.Name; 
    } 
} 

class ClassSearch 
{ 
    public ClassSearch(Expression<Func<object, object>> e) 
    { 
    Property = new PropertyNameAndValue(e); 
    } 

    public PropertyNameAndValue Property { get; private set; } 


    public override string ToString() 
    { 
    return String.Format("{0} = '{1}'", Property.Name, Property); 
    } 
} 

class PropertyNameAndValue 
{ 
    private readonly Func<object, object> _func; 

    public PropertyNameAndValue(Expression<Func<object, object>> e) 
    { 
    _func = e.Compile(); 
    Name = Reflector.GetPropertyName(e); 
    } 

    public object GetValue(object propOwner) 
    { 
    return _func.Invoke(propOwner); 
    } 

    public string Name { get; private set; } 
} 


class SomeClass 
{ 
    public string Property { get; set; } 
} 

Основная часть этого примера является метод Reflector.GetPropertyName(...), который возвращает имя свойства в выражении. То есть Reflector.GetPropertyName(s => ((SomeClass)s).Property) вернет «Свойство».

преимущество является: Это типобезопасным, потому что в new ClassSearch(s => s.Property) компиляции закончится с ошибкой, если SomeClass не будет иметь свойство «Property».

Недостаток: Это не безопасный тип, потому что, если вы пишете, например, new ClassSearch(s => s.Method()), и там был бы метод 'Method', тогда не было бы ошибки компиляции, кроме ошибки времени выполнения.

Смежные вопросы