类的强类型搜索功能

本文关键字:功能 搜索 强类型 | 更新日期: 2023-09-27 18:27:05

我正在尝试用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'"
    }
}

类的强类型搜索功能

您似乎正在尝试创建一个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;}
}

如果没有更简单的答案,我会试试这个
您可以使用表达式,如下所示:

// 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",则不会有编译错误,而是运行时错误。