使用类型和操作在 C# 中查找 table
Look-up table in C# with Types and Actions
我想将我的 many if 更改为查找 table。
我有类型和方法。我想把它们配对。
if (propertyType == typeof(bool) || propertyType == typeof(bool?))
DoBool(propertyType);
if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
DoDateTime(propertyType);
if (propertyType == typeof(Guid) || propertyType == typeof(Guid?))
DoGuid(propertyType);
我必须创建一个 Dictionary<Type, Action>()
?或者哪种方法最优雅?
你能给我一些建议吗?我可以从哪里开始或在哪里可以找到解决方案?
您可以创建 Dictionary<Type, Action<Type>>
:
var dict = new Dictionary<Type, Action<Type>>() {
{typeof(bool), DoBool},
{typeof(bool?), DoBool},
{typeof(DateTime), DoDateTime},
{typeof(Datetime?), DoDateTime},
{typeof(Guid), DoGuid},
{typeof(Guid?), DoGuid}
};
然后这样称呼它:
dict[propertyType](propertyType)
您可以创建一个方法来使用指定类型初始化查找 table,以避免重复。
private readonly IDictionary<Type, Action<Type>> _lookup;
然后你可以定义初始化方法 _dict
,
private void AddEntry<T>(Action<Type> action) where T : struct
{
_lookup[typeof(T)] = action;
_lookup[typeof(Nullable<T>)] = action;
}
private void DoInt(Type type) { /* implementation */ }
AddEntry<bool>(type => { /* implementation */ });
AddEntry<int>(DoInt);
因为这更多的是控制代码流而不是纯粹的查找,我可能会使用面向对象的方法并将每个 "handler" 的代码放在单独的 classes 中(使用公共基地里面的东西 class)。
你可以创建一个像
这样的通用接口
public interface ITypeHandler {
void HandleType(Type type);
}
... 如果愿意,将处理程序的实现放在类型 Dictionary<Type, ITypeHandler>
的字典中,或者您可以在接口上有一个 属性 来显示它处理的类型和 select 来自基于此 属性.
的(可能是依赖注入的)处理程序列表
这增加了关注点分离、可测试性等好处。
(请注意,*Handler 不是一个很好的名称,您必须根据所涵盖的场景创建一个更好的名称。)
我创建了自己的实现,有点不同,但我使用了@DaggeJ 的建议,非常感谢!
首先,我创建了一个基本处理程序 class。之后我在不同类型 classes 上使用了这个基础。你可以在下面看到它。
基类:
public abstract class QueryHandler<T> where T : class
{
//I added here more property.
public abstract Type[] Types { get; }
protected QueryHandler(//Properties)
{
//Properties null check
}
public abstract IQueryable<T> Handle();
}
后代 class:
internal class GuidQuery<T> : QueryHandler<T> where T : class
{
public override Type[] Types => new Type[] { typeof(Guid), typeof(Guid?) };
public GuidQuery(//Properties) : base(//Properties)
{
}
public override IQueryable<T> Handle()
{
// Implementation
}
}
用法:
public IQueryable<T> GetQuery()
{
var queryHandlerList = new List<QueryHandler<T>>()
{
new IntQuery<T>(//Properties),
new DateTimeQuery<T>(//Properties),
new StringQuery<T>(//Properties),
new BoolQuery<T>(//Properties),
new GuidQuery<T>(//Properties),
new EnumQuery<T>(//Properties)
};
}
return query = queryHandlerList.FirstOrDefault(h => GetType<T>(h, property.PropertyType)).Handle();
private bool GetType<T>(QueryHandler<T> handler, Type type) where T: class
{
if (handler.Types.FirstOrDefault(t => t == type) == type || handler.Types.FirstOrDefault(t => t == type.BaseType) == type.BaseType) return true;
return false;
}
我想将我的 many if 更改为查找 table。
我有类型和方法。我想把它们配对。
if (propertyType == typeof(bool) || propertyType == typeof(bool?))
DoBool(propertyType);
if (propertyType == typeof(DateTime) || propertyType == typeof(DateTime?))
DoDateTime(propertyType);
if (propertyType == typeof(Guid) || propertyType == typeof(Guid?))
DoGuid(propertyType);
我必须创建一个 Dictionary<Type, Action>()
?或者哪种方法最优雅?
你能给我一些建议吗?我可以从哪里开始或在哪里可以找到解决方案?
您可以创建 Dictionary<Type, Action<Type>>
:
var dict = new Dictionary<Type, Action<Type>>() {
{typeof(bool), DoBool},
{typeof(bool?), DoBool},
{typeof(DateTime), DoDateTime},
{typeof(Datetime?), DoDateTime},
{typeof(Guid), DoGuid},
{typeof(Guid?), DoGuid}
};
然后这样称呼它:
dict[propertyType](propertyType)
您可以创建一个方法来使用指定类型初始化查找 table,以避免重复。
private readonly IDictionary<Type, Action<Type>> _lookup;
然后你可以定义初始化方法 _dict
,
private void AddEntry<T>(Action<Type> action) where T : struct
{
_lookup[typeof(T)] = action;
_lookup[typeof(Nullable<T>)] = action;
}
private void DoInt(Type type) { /* implementation */ }
AddEntry<bool>(type => { /* implementation */ });
AddEntry<int>(DoInt);
因为这更多的是控制代码流而不是纯粹的查找,我可能会使用面向对象的方法并将每个 "handler" 的代码放在单独的 classes 中(使用公共基地里面的东西 class)。
你可以创建一个像
这样的通用接口public interface ITypeHandler {
void HandleType(Type type);
}
... 如果愿意,将处理程序的实现放在类型 Dictionary<Type, ITypeHandler>
的字典中,或者您可以在接口上有一个 属性 来显示它处理的类型和 select 来自基于此 属性.
这增加了关注点分离、可测试性等好处。
(请注意,*Handler 不是一个很好的名称,您必须根据所涵盖的场景创建一个更好的名称。)
我创建了自己的实现,有点不同,但我使用了@DaggeJ 的建议,非常感谢!
首先,我创建了一个基本处理程序 class。之后我在不同类型 classes 上使用了这个基础。你可以在下面看到它。
基类:
public abstract class QueryHandler<T> where T : class
{
//I added here more property.
public abstract Type[] Types { get; }
protected QueryHandler(//Properties)
{
//Properties null check
}
public abstract IQueryable<T> Handle();
}
后代 class:
internal class GuidQuery<T> : QueryHandler<T> where T : class
{
public override Type[] Types => new Type[] { typeof(Guid), typeof(Guid?) };
public GuidQuery(//Properties) : base(//Properties)
{
}
public override IQueryable<T> Handle()
{
// Implementation
}
}
用法:
public IQueryable<T> GetQuery()
{
var queryHandlerList = new List<QueryHandler<T>>()
{
new IntQuery<T>(//Properties),
new DateTimeQuery<T>(//Properties),
new StringQuery<T>(//Properties),
new BoolQuery<T>(//Properties),
new GuidQuery<T>(//Properties),
new EnumQuery<T>(//Properties)
};
}
return query = queryHandlerList.FirstOrDefault(h => GetType<T>(h, property.PropertyType)).Handle();
private bool GetType<T>(QueryHandler<T> handler, Type type) where T: class
{
if (handler.Types.FirstOrDefault(t => t == type) == type || handler.Types.FirstOrDefault(t => t == type.BaseType) == type.BaseType) return true;
return false;
}