[英]Define a class MyClass<T> or a function MyFunction<T>(T x) where T can only by a type that implements IMyInterface
[英]Keep a Dictionary<Type, MyClass<T>> where elements are referenceable by type
我有一個名為EntityTypeTransform的抽象類,它有一個抽象方法,用於保存將IDataRecord轉換為T實例的Func委托。
public abstract class EntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransform();
}
該類的實現可能看起來像(看起來像):
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransform()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
現在我想在通用字典中保留每個類的實例,例如:
Dictionary<Type, EntityTypeTransform<T>>
但這不起作用,因為(例如)EntityTypeTransform Of Task的實例與EntityTypeTransform Of TaskParameter的實例不同。
誰能幫我嗎?
編輯:我應該添加Type key = typeof(T)
實際上,你根本不需要使用字典! 您可以使用GenericClass<T>
實際上是每個T的不同類型的事實,因此它可以有自己的靜態字段(即GenericClass<Foo>.SomeField
不與GenericClass<Bar>.SomeField
共享)
例如,您可以像這樣實現緩存:
static class TransformCache<TEntityType>
{
public static EntityTypeTransform<TEntityType> Transform { get; set; }
}
並像這樣使用它:
TransformCache<TaskParameter>.Transform = new TaskParameterEntityTypeTransform();
您不能指定包含不同泛型類型的強類型集合。 這是我在類似問題中使用的方法,經過修改以符合您的要求:
class TransformCollection
{
private Hashtable cache = new Hashtable();
public void Add<T>(EntityTypeTransform<T> transform) where T : class
{
this.cache[typeof(T)] = itemToCache;
}
public bool Exists<T>() where T : class
{
return this.cache.ContainsKey(typeof(T));
}
public EntityTypeTransform<T> Get<T>() where T : class
{
if (!this.Exists<T>())
throw new ArgumentException("No cached transform of type: " + typeof(T).Name);
return this.cache[typeof(T)] as EntityTypeTransform<T>;
}
}
這為您的泛型類型提供了類型安全的緩存(盡管類的安全性是由類的邏輯強制執行的,而不是C#)。 您可以按如下方式使用它:
var collection = new TransformCollection();
collection.Add(SomeMethodToGetTransform<Task>());
//...
if (collection.Exists<Task>())
{
var transform = collection.Get<Task>();
//...
}
您可以使用非泛型的接口,然后在該抽象類中顯式實現該接口,這在.Net庫本身中非常常見:
public interface IEntityTypeTransform
{
Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<TEntityType> : IEntityTypeTransform
where TEntityType : class
{
public virtual Func<IDataRecord, TEntityType> GetDataTransform()
{
return this.GetDataTransformImpl();
}
public abstract Func<IDataRecord, TEntityType> GetDataTransformImpl();
Func<IDataRecord, object> IEntityTypeTransform.GetDataTransform()
{
return this.GetDataTransform();
}
}
您必須創建一個非泛型基類,例如
public abstract class EntityTypeTransformBase
{
public abstract Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<TEntityType> : EntityTypeTransformBase where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransformImpl();
public override Func<IDataRecord, object> GetDataTransform()
{
return GetDataTransformImpl();
}
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransformImpl()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
現在您可以創建您的字典:
var d = new Dictionary<Type, EntityTypeTransformBase>();
d.Add(typeof(TaskParameter), new TaskParameterEntityTypeTransform());
您可以使用KeyedByTypeCollection
來獲取類型安全性,並且可以使用協變類型參數定義接口,以確保只能將類型為EntityTypeTransform<T>
對象添加到字典中:
public interface IEntityTypeTransform<out TEntityType> where TEntityType : class
{
TEntityType Transform(IDataRecord dataRecord);
}
public abstract class EntityTypeTransform<TEntityType> : IEntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract TEntityType Transform(IDataRecord dataRecord);
}
public class TaskParameter
{
public int TaskId;
public string Name;
public string Value;
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override TaskParameter Transform(IDataRecord dataRecord)
{
return new TaskParameter()
{
TaskId = (int)dataRecord["task_id"],
Name = (string)dataRecord["p_name"],
Value = (string)dataRecord["p_value"]
};
}
}
public class SomeClass
{
public KeyedByTypeCollection<IEntityTypeTransform<object>> TransformDictionary = new KeyedByTypeCollection<IEntityTypeTransform<object>>()
{
new TaskParameterEntityTypeTransform(),
// More transforms here
};
}
現在您可以像這樣使用它:
public void SomeMethod(IDataRecord dataRecord)
{
TaskParameter taskParameter = TransformDictionary.Find<TaskParameterEntityTypeTransform>().Transform(dataRecord);
}
為變換器添加非通用接口:
public interface IEntityTypeTransform
{
Func<IDataRecord, object> GetDataTransform();
}
public abstract class EntityTypeTransform<T> : IEntityTypeTransform
{
public abstract Func<IDataRecord, object> GetDataTransform();
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, object> GetDataTransform()
{
return dataRecord => new TaskParameter()
{
TaskId = (int)dataRecord["task id"],
};
}
}
然后,您可以封裝字典以確保數據類型始終匹配。 永遠不允許添加錯誤類型的IEntityTypeTransform:
public class TransformDistributor
{
private readonly Dictionary<Type, IEntityTypeTransform> _transforms = new Dictionary<Type, IEntityTypeTransform>();
public void Add<T>(EntityTypeTransform<T> type)
{
this._transforms.Add(typeof(T), type);
}
public T Transform<T>(IDataRecord record)
{
var transform = this._transforms[typeof(T)].GetDataTransform()(record);
if (transform is T)
{
return (T)transform;
}
else
{
// theorically can't happen
throw new InvalidOperationException("transformer doesn't return instance of type " + transform.GetType().Name);
}
}
}
優點是在編譯時,即使您沒有使用泛型,也確保沒有人可以插入壞變壓器。
用法:
var transforms = new TransformDistributor();
transforms.Add<TaskParameter>(new TaskParameterEntityTypeTransform());
var taskParameter = transforms.Transform<TaskParameter>(new DataRecord());
我試圖了解你到底想要什么,我希望這正是你所尋找的!
您應在TaskParameter類中設置正確的參數:TaskId,Name,Value
public abstract class EntityTypeTransform<TEntityType> where TEntityType : class
{
public abstract Func<IDataRecord, TEntityType> GetDataTransform();
}
public class TaskParameterEntityTypeTransform : EntityTypeTransform<TaskParameter>
{
public override Func<IDataRecord, TaskParameter> GetDataTransform()
{
return x => new TaskParameter { X = x.FieldCount };
}
}
public class TaskParameter
{
public int X { get; set; }
}
Dictionary<Type, EntityTypeTransform<TaskParameter>> imADict;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.