我的域模型具有多个NewsType,它们是NewsItem的子类,如下所示(简化):
public abstract class NewsItem : Entity
{
public virtual Account Account { get; set; }
public virtual DateTime DateTime { get; set; }
}
这是NewsItem的几个子类:
public class NewsItemJoiner : NewsItem
{
public virtual Account AccountJoined { get; set; }
}
public class NewsItemStatus : NewsItem
{
public virtual string Status { get; set; }
}
在我的MVC应用程序中,我想返回一个Newsitem的集合,其中可能包含NewsItem的许多不同子类。我现在需要做的是遍历每个新闻项,并为该特定类型的NewsItem从相关类中调用Render函数...代码可能会更容易地解释这一点:
public interface IRenderer<T> where T : NewsItem
{
string Render(T item);
}
public class JoinedRenderer : IRenderer<NewsItemJoiner>
{
public string Render(NewsItemJoiner item)
{
return String.Format("{0} has just joined our music network.", item.AccountJoined.ArtistName);
}
}
public class StatusUpdateRenderer : IRenderer<NewsItemStatus>
{
public string Render(NewsItemStatus item)
{
return String.Format("<span class='statusupdate'>{0}<span>", item.Status);
}
}
我需要以某种方式根据NewsItem的类型调用正确的类Render函数。
最佳答案
一种可能:启动时(即在与渲染代码相关的静态构造函数中),遍历程序集中的类并实例化并存储映射到其渲染类型的Dictionary<Type, object>
实现实例的IRenderer<T>
。
(此建议假设渲染器对象是线程安全的,因为您可能最终一次从多个请求线程中调用Render
方法。如果它们不是线程安全的,则您需要更改字典<Type, Type>
并为每次使用实例化渲染器。)
例如:
public class RenderUtil
{
static Dictionary<Type, object> s_renderers;
static RenderUtil()
{
s_renderers = new Dictionary<Type, object>();
foreach (var type in Assembly.GetExecutingAssembly().GetTypes())
{
var renderInterface = type.GetInterfaces().FirstOrDefault(
i => i.IsGenericType &&
i.GetGenericTypeDefinition() == typeof(IRenderer<>));
if (renderInterface != null)
{
s_renderers.Add(
renderInterface.GetGenericArguments()[0],
Activator.CreateInstance(type));
}
}
}
public static string Render<T>(T item)
{
IRenderer<T> renderer = null;
try
{
// no need to synchronize readonly access
renderer = (IRenderer<T>)s_renderers[item.GetType()];
}
catch
{
throw new ArgumentException("No renderer for type " + item.GetType().Name);
}
return renderer.Render(item);
}
}
用法:
var newsItem = new NewsItemStatus();
// in your example code, ends up calling StatusUpdateRenderer.Render:
var rendered = RenderUtil.Render(newsItem);
请注意,如果给定类型有多个渲染器,则第一次使用时,
RenderUtil
类将通过DuplicateKeyException
抛出TypeInitializationException
。关于c# - C#泛型-根据对象类型查找正确的具体类,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/2274697/