我创建了一个自定义属性选择器来接受构造函数中的一个数组,以说明哪些属性应该包含在搜索中。只要没有组件类型,该方法就可以很好地工作,但是我该如何处理呢?这是一个例子:
public class Customer
{
public virtual int Id { get; private set; }
public virtual Name Name { get; set; }
public virtual bool isPreferred { get; set; }
//...etc
}
public class Name
{
public string Title { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
public string Fullname { get; }
}
public class CustomerPropertySelector : Example.IPropertySelector
{
private string[] _propertiesToInclude = { };
public CustomerPropertySelector(string[] propertiesToInclude)
{
this._propertiesToInclude = propertiesToInclude;
}
public bool Include(object propertyValue, String propertyName, NHibernate.Type.IType type)
{
//...Checking for null and zeros etc, excluded for brevity
if (!_propertiesToInclude.Contains(propertyName))
return false;
return true;
}
}
我希望能够按名字搜索,但不一定是最后一个。然而,属性名称是 Name,因此名字和姓氏似乎都是同一个属性的一部分,而像 Name.Firstname 这样通常用作标准的东西似乎在这里不起作用。最好的解决方法是什么?
例子:
Customer exampleCust = new Customer(FirstName: "Owen");
IList<Customer> matchedCustomers = _custRepo.GetByExample(exampleCust, new string[] { "Name.FirstName" });
鉴于 db 中有 2 个客户,只有一个名为“Owen”,但两者都有isPreferred = false
,我希望我的查询只返回第一个。标准 QBE 将根据isPreferred
属性返回两者。
解决方案:
感谢您的回答,该解决方案主要基于 therealmitchconnors 的回答,但是如果没有 Mark Perry 的回答,我也无法做到。
诀窍是要意识到Name.FirstName
我实际上想要排除而不是包含属性,Name.LastName
因为 QBE 只允许我们排除属性。我使用了一种改编自 therealmitchconnors 答案的方法来帮助我确定属性的完全限定名称。这是工作代码:
public IList<T> GetByExample(T exampleInstance, params string[] propertiesToInclude)
{
ICriteria criteria = _session.CreateCriteria(typeof(T));
Example example = Example.Create(exampleInstance);
var props = typeof(T).GetProperties();
foreach (var prop in props)
{
var childProperties = GetChildProperties(prop);
foreach (var c in childProperties)
{
if (!propertiesToInclude.Contains(c))
example.ExcludeProperty(c);
}
}
criteria.Add(example);
return criteria.List<T>();
}
private IEnumerable<string> GetChildProperties(System.Reflection.PropertyInfo property)
{
var builtInTypes = new List<Type> { typeof(bool), typeof(byte), typeof(sbyte), typeof(char),
typeof(decimal), typeof(double), typeof(float), typeof(int), typeof(uint), typeof(long),
typeof(ulong), typeof(object), typeof(short), typeof(ushort), typeof(string), typeof(DateTime) };
List<string> propertyNames = new List<string>();
if (!builtInTypes.Contains(property.PropertyType) && !property.PropertyType.IsGenericType)
{
foreach (var subprop in property.PropertyType.GetProperties())
{
var childNames = GetChildProperties(subprop);
propertyNames = propertyNames.Union(childNames.Select(r => property.Name + "." + r)).ToList();
}
}
else
propertyNames.Add(property.Name);
return propertyNames;
}
我不确定确定属性是否为组件类的最佳方法,非常欢迎任何有关如何改进代码的建议。