C# 每当第一次使用对象时自动调用init函数
我有一个对象,它在构造时(快速)仅使用裸骨数据初始化自身,在首次访问时(慢速)加载自身。我的想法是,我在启动时创建了很多这样的裸体对象,并将它们散列到一个映射中,然后在第一次单独访问每个对象时完全加载它们。问题是我不能保证客户端将如何与这个对象交互,可能会调用多个公共方法 有没有一个好的模式来支持这种情况?显而易见(也是我目前的)解决方案是使用内部bool跟踪状态,在每个可能被调用的函数中检查bool,并以这种方式加载。但这需要在所有公共函数中复制该行为的代码,并且容易出错C# 每当第一次使用对象时自动调用init函数,c#,load,delay,init,C#,Load,Delay,Init,我有一个对象,它在构造时(快速)仅使用裸骨数据初始化自身,在首次访问时(慢速)加载自身。我的想法是,我在启动时创建了很多这样的裸体对象,并将它们散列到一个映射中,然后在第一次单独访问每个对象时完全加载它们。问题是我不能保证客户端将如何与这个对象交互,可能会调用多个公共方法 有没有一个好的模式来支持这种情况?显而易见(也是我目前的)解决方案是使用内部bool跟踪状态,在每个可能被调用的函数中检查bool,并以这种方式加载。但这需要在所有公共函数中复制该行为的代码,并且容易出错 我可以想象一个单一的
我可以想象一个单一的入口点方法,然后根据客户请求类型等来列出行为,但是在我考虑下一条路之前,我想看看是否有一个我可能不知道的普遍接受的方法/模式。我用C#来做这件事,但任何见解都值得赞赏。
如果我了解您想要实现的目标,那么您正在寻找代理设计模式,更具体地说,是虚拟代理 指 一个小例子如下: public abstract class IObjectProvider
{
public abstract IObjectProvider Object{get;}
public abstract void doStuff();
}
public class RealObject : IObjectProvider
{
public RealObject()
{
//Do very complicated and time taking stuff;
}
public override IObjectProvider Object
{
get { return this; }
}
public override void doStuff()
{
//do this stuff that these objects normally do
}
}
public class ObjectProxy : IObjectProvider
{
private IObjectProvider objectInstance = null;
public override IObjectProvider Object
{
get
{
if (objectInstance == null)
objectInstance = new RealObject();
return objectInstance;
}
}
public override void doStuff()
{
if(objectInstance!=null)
objectInstance.doStuff();
}
}
public class SkeletonClass
{
public IObjectProvider Proxy1 = new ObjectProxy();
public IObjectProvider Proxy2 = new ObjectProxy();
}
static void Main(String[] args)
{
//Objects Not Loaded
SkeletonClass skeleton = new SkeletonClass();
//Proxy1 loads object1 on demand
skeleton.Proxy1.Object.doStuff();
//Proxy2 not loaded object2 until someone needs it
}
下面是一个动态代理方法的示例
using System;
using System.Diagnostics;
using Castle.DynamicProxy; //Remember to include a reference, too. It's nugettable package is Castle.Core
namespace ConsoleApp
{
public class ActualClass
{
//Have static instances of two below for performance
private static ProxyGenerator pg = new ProxyGenerator();
private static ActualClassInterceptor interceptor = new ActualClassInterceptor();
//This is how we get ActualClass items that are wrapped in the Dynamic Proxy
public static ActualClass getActualClassInstance()
{
ActualClass instance = new ActualClass();
return pg.CreateClassProxyWithTarget<ActualClass>(instance, interceptor);
}
//Tracking whether init has been called
private bool initialized = false;
//Will be used as evidence of true initialization, i.e. no longer null
private int? someValue = null;
public void Initialize()
{
if (!initialized)
{
//do some initialization here.
someValue = -1; //Will only get set to non-null if we've run this line.
initialized = true;
}
}
//Any methods you want to intercept need to be virtual!
public virtual int replaceValue(int value)
{
//below will blow up, if someValue has not been set to -1 via Initialize();
int oldValue = someValue.Value;
someValue = value;
return oldValue;
}
//block off constructor from public to enforce use of getActualClassInstance
protected ActualClass() { }
}
public class ActualClassInterceptor : ActualClass, IInterceptor
{
public void Intercept(IInvocation invocation)
{
//Call initialize before proceeding to call the intercepted method
//Worth noting that this is the only place we actually call Initialize()
((ActualClass)invocation.InvocationTarget).Initialize();
invocation.Proceed();
}
}
class Program
{
static void Main(string[] args)
{
ActualClass instance1 = ActualClass.getActualClassInstance();
ActualClass instance2 = ActualClass.getActualClassInstance();
int x1 = instance1.replaceValue(41);
int x2 = instance2.replaceValue(42);
int y1 = instance1.replaceValue(82);
Debug.Assert(y1 == 41);
int y2 = instance2.replaceValue(84);
Debug.Assert(y2 == 42);
var read = Console.ReadKey();
}
}
}
使用系统;
使用系统诊断;
使用Castle.DynamicProxy//记住也要包括一个参考资料。这是一个可获取的包是Castle.Core
名称空间控制台
{
公共类实际类
{
//为提高性能,请使用下面两个的静态实例
专用静态ProxyGenerator pg=新ProxyGenerator();
私有静态ActualClassInterceptor拦截器=新的ActualClassInterceptor();
//这就是我们如何获得包装在动态代理中的实际类项
公共静态ActualClass GetActualClass实例()
{
ActualClass实例=新的ActualClass();
返回pg.CreateClassProxyWithTarget(实例,拦截器);
}
//跟踪是否已调用init
private bool initialized=false;
//将用作真实初始化的证据,即不再为空
私有int?someValue=null;
公共无效初始化()
{
如果(!已初始化)
{
//在这里进行一些初始化。
someValue=-1;//仅当我们运行这一行时才会设置为非null。
初始化=真;
}
}
//您想要拦截的任何方法都需要是虚拟的!
公共虚拟整数替换值(整数值)
{
//如果未通过Initialize()将someValue设置为-1,则下面的代码将爆炸;
int oldValue=someValue.Value;
someValue=值;
返回旧值;
}
//阻止公共构造函数以强制使用getActualClassInstance
受保护的实际类(){}
}
公共类ActualClass拦截器:ActualClass,IInterceptor
{
公共无效拦截(IInvocation调用)
{
//在继续调用被拦截的方法之前调用initialize
//值得注意的是,这是我们实际调用Initialize()的唯一地方
((ActualClass)invocation.InvocationTarget).Initialize();
invocation.procedure();
}
}
班级计划
{
静态void Main(字符串[]参数)
{
ActualClass实例1=ActualClass.getActualClassInstance();
ActualClass实例2=ActualClass.GetActualClass实例();
int x1=实例1.replaceValue(41);
int x2=instance2.replaceValue(42);
inty1=instance1.replaceValue(82);
Assert(y1==41);
int y2=instance2.replaceValue(84);
Assert(y2==42);
var read=Console.ReadKey();
}
}
}
不要说这是一种正确的方法,性能开销可能不适合您的用例,但您可以使用动态代理。这将拦截每个方法调用,并在继续方法调用之前进行进一步初始化。