Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 每当第一次使用对象时自动调用init函数_C#_Load_Delay_Init - Fatal编程技术网

C# 每当第一次使用对象时自动调用init函数

C# 每当第一次使用对象时自动调用init函数,c#,load,delay,init,C#,Load,Delay,Init,我有一个对象,它在构造时(快速)仅使用裸骨数据初始化自身,在首次访问时(慢速)加载自身。我的想法是,我在启动时创建了很多这样的裸体对象,并将它们散列到一个映射中,然后在第一次单独访问每个对象时完全加载它们。问题是我不能保证客户端将如何与这个对象交互,可能会调用多个公共方法 有没有一个好的模式来支持这种情况?显而易见(也是我目前的)解决方案是使用内部bool跟踪状态,在每个可能被调用的函数中检查bool,并以这种方式加载。但这需要在所有公共函数中复制该行为的代码,并且容易出错 我可以想象一个单一的

我有一个对象,它在构造时(快速)仅使用裸骨数据初始化自身,在首次访问时(慢速)加载自身。我的想法是,我在启动时创建了很多这样的裸体对象,并将它们散列到一个映射中,然后在第一次单独访问每个对象时完全加载它们。问题是我不能保证客户端将如何与这个对象交互,可能会调用多个公共方法

有没有一个好的模式来支持这种情况?显而易见(也是我目前的)解决方案是使用内部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();
}
}
}

不要说这是一种正确的方法,性能开销可能不适合您的用例,但您可以使用动态代理。这将拦截每个方法调用,并在继续方法调用之前进行进一步初始化。