C# 即时加载和存储单例
作为尝试对另一个问题提出答案的一部分,我想创建一个自注册单例实例的C# 即时加载和存储单例,c#,design-patterns,initialization,singleton,static-constructor,C#,Design Patterns,Initialization,Singleton,Static Constructor,作为尝试对另一个问题提出答案的一部分,我想创建一个自注册单例实例的字典。具体来说,是这样的: public abstract class Role { public static Dictionary<string, Role> Roles = new Dictionary<string, Role>(); protected Role() { _roles.Add(this.Name, this); } pub
字典。具体来说,是这样的:
public abstract class Role
{
public static Dictionary<string, Role> Roles = new Dictionary<string, Role>();
protected Role()
{
_roles.Add(this.Name, this);
}
public abstract string Name { get; }
}
public class AdminRole : Role
{
public static readonly AdminRole Instance = new AdminRole();
public override string Name { get { return "Admin"; } }
}
如果您没有获得KeyNotFound
异常(或null
),则此操作成功
可以显式初始化Role
(例如Role.Initialize()
),但不能初始化子类-其思想是能够添加一个子类,以便字典拥有它,而无需更改任何预先存在的内容。Hm。。有一个真正的问题,用户可以创建他的AppDomains。在当前进程中没有获取所有加载的AppDomain的好方法。我使用网络中创建的坏黑客:。结果代码:
public static void Main()
{
Console.WriteLine(Role.GetRole("Admin").Ololo);
}
public static class AppDomainExtensions {
public static List<AppDomain> GetAllAppDomains() {
List<AppDomain> appDomains = new List<AppDomain>();
IntPtr handle = IntPtr.Zero;
ICorRuntimeHost host = (ICorRuntimeHost)(new CorRuntimeHost());
try
{
host.EnumDomains(out handle);
while (true)
{
object domain;
host.NextDomain(handle, out domain);
if (domain == null)
break;
appDomains.Add((AppDomain)domain);
}
}
finally
{
host.CloseEnum(handle);
}
return appDomains;
}
[ComImport]
[Guid("CB2F6723-AB3A-11d2-9C40-00C04FA30A3E")]
private class CorRuntimeHost// : ICorRuntimeHost
{
}
[Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface ICorRuntimeHost
{
void CreateLogicalThreadState ();
void DeleteLogicalThreadState ();
void SwitchInLogicalThreadState ();
void SwitchOutLogicalThreadState ();
void LocksHeldByLogicalThread ();
void MapFile ();
void GetConfiguration ();
void Start ();
void Stop ();
void CreateDomain ();
void GetDefaultDomain ();
void EnumDomains (out IntPtr enumHandle);
void NextDomain (IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)]out object appDomain);
void CloseEnum (IntPtr enumHandle);
void CreateDomainEx ();
void CreateDomainSetup ();
void CreateEvidence ();
void UnloadDomain ();
void CurrentDomain ();
}
}
public abstract class Role
{
private static Dictionary<string, Role> Roles = new Dictionary<string, Role>();
public static Role GetRole(string key) {
if (Roles.ContainsKey(key))
return Roles[key];
foreach (var appDomain in AppDomainExtensions.GetAllAppDomains()) {
foreach (var assembly in appDomain.GetAssemblies()) {
var type = assembly.GetTypes().Where(t => t.Name == key + "Role").FirstOrDefault();// (key + "Role", false, true);
if (type == null || !typeof(Role).IsAssignableFrom(type))
continue;
Role role = null;
{
var fieldInfo = type.GetField("Instance", BindingFlags.Static | BindingFlags.Public);
if (fieldInfo != null) {
role = fieldInfo.GetValue(null) as Role;
}
else {
var propertyInfo = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
if (propertyInfo != null)
role = propertyInfo.GetValue(null, null) as Role;
}
}
if (role == null)
continue;
Roles[key] = role;
return role;
}
}
throw new KeyNotFoundException();
}
public string Ololo {get;set;}
}
public class AdminRole : Role
{
public static readonly AdminRole Instance = new AdminRole();
private AdminRole() {
Ololo = "a";
}
}
publicstaticvoidmain()
{
Console.WriteLine(Role.GetRole(“Admin”).Ololo);
}
公共静态类AppDomainExtensions{
公共静态列表GetAllAppDomains(){
List appDomains=新列表();
IntPtr handle=IntPtr.Zero;
ICorRuntimeHost主机=(ICorRuntimeHost)(新的CorRuntimeHost());
尝试
{
主机。枚举域(外句柄);
while(true)
{
对象域;
host.NextDomain(句柄,域外);
如果(域==null)
打破
添加((AppDomain)域);
}
}
最后
{
host.CloseEnum(句柄);
}
返回appDomains;
}
[ComImport]
[Guid(“CB2F6723-AB3A-11d2-9C40-00C04FA30A3E”)]
私有类CorRuntimeHost/:ICorRuntimeHost
{
}
[Guid(“CB2F6722-AB3A-11D2-9C40-00C04FA30A3E”)]
[接口类型(ComInterfaceType.InterfaceSiunknown)]
专用接口ICorRuntimeHost
{
void CreateLogicalThreadState();
void DeleteLogicalThreadState();
void SwitchInLogicalThreadState();
void SwitchOutLogicalThreadState();
void LocksHeldByLogicalThread();
void映射文件();
void GetConfiguration();
void Start();
无效停止();
void CreateDomain();
void GetDefaultDomain();
void EnumDomains(out IntPtr enumHandle);
void NextDomain(IntPtr enumHandle,[marshallas(UnmanagedType.IUnknown)]out object appDomain;
void CloseEnum(IntPtr enumHandle);
void CreateDomainEx();
void CreateDomainSetup();
无效证据();
无效添加域();
void CurrentDomain();
}
}
公共抽象类角色
{
私有静态字典角色=新字典();
公共静态角色GetRole(字符串键){
if(角色.容器(关键))
返回角色[键];
foreach(AppDomainExtensions.GetAllAppDomains()中的var appDomain){
foreach(appDomain.GetAssemblies()中的var程序集){
var type=assembly.GetTypes()。其中(t=>t.Name==key+“Role”).FirstOrDefault();/(key+“Role”,false,true);
if(type==null | |!typeof(Role).IsAssignableFrom(type))
继续;
Role=null;
{
var fieldInfo=type.GetField(“实例”,BindingFlags.Static | BindingFlags.Public);
如果(fieldInfo!=null){
role=fieldInfo.GetValue(null)作为角色;
}
否则{
var propertyInfo=type.GetProperty(“实例”,BindingFlags.Static | BindingFlags.Public);
if(propertyInfo!=null)
role=propertyInfo.GetValue(null,null)作为角色;
}
}
如果(角色==null)
继续;
角色[关键]=角色;
返回角色;
}
}
抛出新的KeyNotFoundException();
}
公共字符串Ololo{get;set;}
}
公共类管理员角色:角色
{
公共静态只读AdminRole实例=新AdminRole();
私有管理员角色(){
Ololo=“a”;
}
}
我们所做的:我们迭代所有AppDomain,从中获取所有程序集。对于每个程序集,我们尝试查找类型Key+“Role”
(基于约定),检查是否存在问题,获取“Instance”字段
现在,关于黑客:这是个坏主意。如果您将创建包含所有已加载域列表的singleton,效果会更好。创建域时,必须将其添加到列表中;卸载时,必须从列表中删除-从角色和其他类中删除属于域的所有类型。它现在的工作原理:不可能卸载AppDomain,因为它的一种类型上总是有一个链接。如果不需要卸载AppDomains,则可以将此代码保持原样
如果您永远不会创建AppDomain,则只能通过AppDomain.CurrentDomain
程序集进行迭代。您不想在角色中更改字典
-您不想对每个新子类型进行更改,或者您永远不想进行更改?@nsinreal-前者。我希望能够创建一个新的角色
类型,而无需对其进行子类化。好的,明白了。Reflection@nsinreal-原始询问者不想“扫描整个组件以查找IRole
s”。我擅长反射,只要它在角色中是完全独立的。您可以从Role
类中拉出Name
,并通过约定命名使其工作。您可以使用方法GetInstance(key)
或代理类替换字典。调用GetInstance后,首先检查字典。如果没有这样的角色,您将使用GetType(key+“role”)迭代加载到program的所有程序集,并使用它。那太令人印象深刻了。我想我不会提供答案
public static void Main()
{
Console.WriteLine(Role.GetRole("Admin").Ololo);
}
public static class AppDomainExtensions {
public static List<AppDomain> GetAllAppDomains() {
List<AppDomain> appDomains = new List<AppDomain>();
IntPtr handle = IntPtr.Zero;
ICorRuntimeHost host = (ICorRuntimeHost)(new CorRuntimeHost());
try
{
host.EnumDomains(out handle);
while (true)
{
object domain;
host.NextDomain(handle, out domain);
if (domain == null)
break;
appDomains.Add((AppDomain)domain);
}
}
finally
{
host.CloseEnum(handle);
}
return appDomains;
}
[ComImport]
[Guid("CB2F6723-AB3A-11d2-9C40-00C04FA30A3E")]
private class CorRuntimeHost// : ICorRuntimeHost
{
}
[Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
private interface ICorRuntimeHost
{
void CreateLogicalThreadState ();
void DeleteLogicalThreadState ();
void SwitchInLogicalThreadState ();
void SwitchOutLogicalThreadState ();
void LocksHeldByLogicalThread ();
void MapFile ();
void GetConfiguration ();
void Start ();
void Stop ();
void CreateDomain ();
void GetDefaultDomain ();
void EnumDomains (out IntPtr enumHandle);
void NextDomain (IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)]out object appDomain);
void CloseEnum (IntPtr enumHandle);
void CreateDomainEx ();
void CreateDomainSetup ();
void CreateEvidence ();
void UnloadDomain ();
void CurrentDomain ();
}
}
public abstract class Role
{
private static Dictionary<string, Role> Roles = new Dictionary<string, Role>();
public static Role GetRole(string key) {
if (Roles.ContainsKey(key))
return Roles[key];
foreach (var appDomain in AppDomainExtensions.GetAllAppDomains()) {
foreach (var assembly in appDomain.GetAssemblies()) {
var type = assembly.GetTypes().Where(t => t.Name == key + "Role").FirstOrDefault();// (key + "Role", false, true);
if (type == null || !typeof(Role).IsAssignableFrom(type))
continue;
Role role = null;
{
var fieldInfo = type.GetField("Instance", BindingFlags.Static | BindingFlags.Public);
if (fieldInfo != null) {
role = fieldInfo.GetValue(null) as Role;
}
else {
var propertyInfo = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
if (propertyInfo != null)
role = propertyInfo.GetValue(null, null) as Role;
}
}
if (role == null)
continue;
Roles[key] = role;
return role;
}
}
throw new KeyNotFoundException();
}
public string Ololo {get;set;}
}
public class AdminRole : Role
{
public static readonly AdminRole Instance = new AdminRole();
private AdminRole() {
Ololo = "a";
}
}