Я создал пользовательский селектор свойств для принятия массива в конструкторе, чтобы указать, какие свойства должны быть включены в поиск.Подход работает хорошо, пока нет типов компонентов, но как мне с ними бороться?Вот пример:
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" });
Учитывая, что в БД 2 клиента, только один с именем "Оуэн", но обаиметь isPreferred = false
, я бы хотел, чтобы мой запрос возвращал только первый.Стандартный QBE будет возвращать оба, основываясь на свойстве isPreferred
.
РЕШЕНИЕ:
Спасибо за ответы, решение в основном основано на ответе сторонних коннекторов, однако яне мог бы сделать это и без ответа Марка Перри.
Хитрость заключалась в том, чтобы понять, что вместо включения свойства Name.FirstName
я на самом деле хочу исключить Name.LastName
, поскольку QBE позволяет нам исключать только свойства.Я использовал метод, адаптированный на основе ответа от almonchconnors, чтобы помочь мне определить полностью определенные имена свойств.Вот рабочий код:
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;
}
Я не был уверен, что лучше всего определить, является ли свойство классом компонента или нет, любые предложения по улучшению кода приветствуются.