コンストラクターで配列を受け入れて、どのプロパティを検索に含める必要があるかを示すカスタム プロパティ セレクターを作成しました。コンポーネントの種類がない限り、このアプローチはうまく機能しますが、それらをどのように処理すればよいでしょうか? 次に例を示します。
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」という名前の顧客は 1 人だけですが、どちらも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;
}
プロパティがコンポーネント クラスであるかどうかを判断する最善の方法がわかりませんでした。コードを改善する方法についての提案は大歓迎です。