Somewhere deep inside a library in which I do lots of metaprogramming, there is a class that contains the following code:
// Initialized in the constructor
// Destroyed in IDisposable.Dispose
private IDataReader reader;
private T Retrieve<T>()
where T : class, new() {
if (!this.reader.Read())
return null;
// This does the same as typeof(T).GetProperties(), but ReflectionHelper
// memoizes the properties of the types passed to GetProperties.
PropertyInfo[] properties = ReflectionHelper.GetProperties(typeof(T));
T result = new T();
foreach (PropertyInfo property in properties)
property.SetValue(result, this.reader[property.Name], null);
return result;
}
public T RetrieveObject() {
T result = this.RetrieveObject<T>();
this.reader.NextResult();
return result;
}
public List<T> RetrieveList<T>()
where T : class, new() {
List<T> result = new List<T>();
for (T element; (element = this.Retrieve<T>(reader)) != null; )
result.Add(element);
this.reader.NextResult();
return result;
}
Needless to say, the class is a wrapper around IDbConnection
, IDbCommand
and IDataReader
, with the added benefit of allowing sane access to the results.
I want to add the following methods to the class:
public T RetrieveCompound<T, U>()
where T : class, IHeader<U>, new()
where U : class, new() 开发者_如何学Python{
T header = this.RetrieveObject<T>();
if (header != null)
header.Details = this.RetrieveList<U>();
return header;
}
public T RetrieveCompound<T, U, V>()
where T : class, IHeader<U>, IHeader<V>, new()
where U : class, new() {
T header = this.RetrieveObject<T>();
if (header != null) {
((IHeader<U>)header).Details = this.RetrieveList<U>();
((IHeader<V>)header).Details = this.RetrieveList<V>();
}
return header;
}
public T RetrieveCompound<T, U, V, W>()
where T : class, IHeader<U>, IHeader<V>, IHeader<W>, new()
where U : class, new() {
T header = this.RetrieveObject<T>();
if (header != null) {
((IHeader<U>)header).Details = this.RetrieveList<U>();
((IHeader<V>)header).Details = this.RetrieveList<V>();
((IHeader<W>)header).Details = this.RetrieveList<W>();
}
return header;
}
However, this has a very important pitfall: The interface IHeader<T>
happens to be declared in a different assembly, and I do not want to force users of the IDataReader
-wrapper class to add a reference to an assembly they might not need.
I know I could solve this using extension methods, but I am using .NET Framework 2.0. Is there another way to get around this problem?
You could add those methods to a derived type. That way, if you don't need IHeader<T>
-related functionality, you don't need to reference the assembly.
精彩评论