类的强类型搜索功能?

时间:2012-03-08 15:42:48

标签: c# linq properties expression

我正在尝试用c#代码找出一些东西,而且我不是百分之百确定它是否可行,但我正在尝试为几个类实现搜索功能,这些功能简化并且易于开发。现在我有以下代码:

[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'"
    }
}

2 个答案:

答案 0 :(得分:0)

您似乎正在尝试创建一个WCF服务,以便能够传递您喜欢的任何类型。

首先,这不是WSDL友好的。所有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;}
}

答案 1 :(得分: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)会返回“Property”。

优势是:这是类型安全的,因为如果 SomeClass 没有属性'{em>,new ClassSearch(s => s.Property)编译会以错误结束Property ”。

缺点是:这不是类型安全的,因为如果您写例如: new ClassSearch(s => s.Method())并且会有一个方法' Method '然后就会出现编译错误,但会出现运行时错误。