问题描述
我有一个ManagerClass,用于管理从抽象BaseClass派生的类。我需要它,以便只有ManageClass可以访问BaseClass上的某些方法。我还需要某些方法可以在ManagerClass范围之外访问。由于C#没有朋友,所以我将BaseClass封装在ManagerClass中。
问题:
- BaseClass不能从其派生
- 将BaseClass公开,意味着允许在范围之外调用DoStuff()和DoOtherStuff()
我该如何进行这项工作?
公共类ManagerClass
{
//这是一个单例类。
静态ManagerClass实例;
公共静态T CreateBaseClass< T>()其中T:BaseClass,new()
{
//创建并返回一个BaseClass。
// BaseClass中的所有内容都可以在此处访问。
}
抽象类BaseClass()
{
public bool IsRunning {get;组; }
虚拟void DoStuff()
{
//做东西。
}
abstract void DoOtherStuff();
}
}
公共类DerivedClass:ManagerClass.BaseClass
{
公共重写void DoStuff()
{
/ / 做东西。
}
公共重写void DoOtherStuff()
{
//做其他事情。
}
}
class TestClass
{
static void Main(string [] args)
{
//假设这里已经创建了单例。
BaseClass bc = ManagerClass.CreateBaseClass< DerivedClass>();
// bc.IsRunning应该可以访问
// bc.DoStuff()和DoOtherStuff()应该不能访问
}
}
**
更新
**
好吧,所以在找出之后,没有办法让委托为抽象类工作使用泛型,我尝试与工厂一起使用接口。这也不起作用,因为我被迫公开整个BaseClass,或者无法从ManagerClass调用DoStuff()和DoOtherStuff()。然后我意识到我根本不需要工厂,因为DerivedClass调用了BaseClass构造函数,我可以在那里做所有的事情……。
新问题
现在唯一的问题是我为每个BaseClass实例存储一个包装器。由于我只需要将委托存储在BaseClassScope中,如何在调用BaseClass静态构造函数时存储委托,然后如何使用该委托调用最覆盖的方法?
使用系统;
使用System.Collections.Generic;
类程序
{
static void Main(string [] args)
{
ManagerClass.BaseClass [] dc = new DerivedClass [4];
for(int i = 0; i< 4; i ++)
{
dc [i] = new DerivedClass();
//可从外部ManagerClass
dc [i]访问。IsRunning= true;
//无法从ManagerClass外部访问
// dc [i] .DoStuff();
}
ManagerClass.TestManager();
//等待输入。
Console.ReadKey(true);
}
}
class ManagerClass
{
static List< BaseClassWrapper> managedList = new List< BaseClassWrapper>();
公共静态无效TestManager()
{
for(int i = 0; i< managedList.Count; i ++)
{
//可从ManagerClass
managedList [i] .bcs.DoStuff();内部访问。
managedList [i] .bcs.DoOtherStuff();
}
}
类BaseClassScope
{
public Action DoStuff;
public Action DoOtherStuff;
public BaseClassScope(Action ds,Action dos)
{
DoStuff = ds;
DoOtherStuff = dos;
}
}
class BaseClassWrapper
{
public BaseClass bc;
public BaseClassScope bcs;
public BaseClassWrapper(BaseClass bc,BaseClassScope bcs)
{
this.bc = bc;
this.bcs = bcs;
}
}
公共抽象类BaseClass
{
public BaseClass()
{
Console.WriteLine( BaseClass ());
var bcs = new BaseClassScope(DoStuff,DoOtherStuff);
var bcw = new BaseClassWrapper(this,bcs);
managedList.Add(bcw);
}
public bool IsRunning {get;组; }
受保护的虚拟void DoStuff()
{
Console.WriteLine( BaseClass.DoStuff());
}
受保护的抽象void DoOtherStuff();
}
}
class DerivedClass:ManagerClass.BaseClass
{
public DerivedClass()
{
Console.WriteLine( DerivedClass());
}
受保护的覆盖无效DoStuff()
{
Console.WriteLine( DerivedClass.DoStuff());
}
受保护的覆盖无效DoOtherStuff()
{
Console.WriteLine( DerivedClass.DoOtherStuff());
}
}
I认为这将是我的解决方案。它使用奇怪的循环模板模式,但是它不需要所有这些包装器类,并且不使用任何反射。
使用系统;
使用System.Collections.Generic;
名称空间testapp2
{
类程序
{
static void Main()
{
ClassA a = ClassA.Instance ;
ClassB b = ClassB.Instance;
ManagerClass.TestManager();
Console.ReadKey(true);
}
}
}
class ManagerClass
{
静态ManagerClass实例;
静态Dictionary< Type,ManagedClass> managedList =新的Dictionary< Type,ManagedClass>();
公共ManagerClass实例
{
get
{
if(instance == null)
{
instance = new ManagerClass ();
}
返回实例;
}
}
ManagerClass()
{
}
public static void TestManager()
{
foreach(managedList中的var kvp)
{
kvp.Value.doStuffCallback();
kvp.Value.doOtherStuffCallback();
}
}
public static void CreateManagedClass(Type type,Action doStuffCallback,Action doOtherStuffCallback)
{
managedList.Add(type,new ManagedClass( doStuffCallback,doOtherStuffCallback));
}
public static void DestroyManagedClass(Type type)
{
managedList.Remove(type);
}
class ManagedClass
{
public Action doStuffCallback;
public Action doOtherStuffCallback;
public ManagedClass(Action doStuffCallback,Action doOtherStuffCallback)
{
this.doStuffCallback = doStuffCallback;
this.doOtherStuffCallback = doOtherStuffCallback;
}
}
公共抽象类ManagedClassBase< T> T:class,new()
{
静态T实例;
公共静态T实例
{
get
{
if(instance == null)
{
instance = new T();
}
返回实例;
}
}
受保护的ManagedClassBase()
{
CreateManagedClass(typeof(T),DoStuff,DoOtherStuff);
}
〜ManagedClassBase()
{
instance = null;
}
受保护的抽象void DoStuff();
受保护的抽象void DoOtherStuff();
}
}
class ClassA:ManagerClass.ManagedClassBase< ClassA>
{
受保护的覆盖无效DoStuff()
{
Console.WriteLine( ClassA.DoStuff());
}
受保护的覆盖无效DoOtherStuff()
{
Console.WriteLine( ClassA.DoOtherStuff());
}
}
class ClassB:ManagerClass.ManagedClassBase< ClassB>
{
受保护的覆盖无效DoStuff()
{
Console.WriteLine( ClassB.DoStuff());
}
受保护的覆盖无效DoOtherStuff()
{
Console.WriteLine( ClassB.DoOtherStuff());
}
}
I have a ManagerClass that manages classes that derive from an abstract BaseClass. I need it so that only the ManageClass can access certain methods on the BaseClass. I also need certain methods to be accessible outside the scope of the ManagerClass. Since C# doesn't have friends, I'm encapsulating the BaseClass inside the ManagerClass.
The problem:
- BaseClass is not accessible to derive from
- Making BaseClass public,means allowing DoStuff() and DoOtherStuff()to be called from outside the scope of ManagerClass, which I don't want.
How can I make this work?
public class ManagerClass
{
// This is a singleton class.
static ManagerClass instance;
public static T CreateBaseClass<T>() where T : BaseClass, new()
{
// Create and return a BaseClass.
// Everything in BaseClass should be accessible here.
}
abstract class BaseClass()
{
public bool IsRunning { get; set; }
virtual void DoStuff()
{
// Do stuff.
}
abstract void DoOtherStuff();
}
}
public class DerivedClass : ManagerClass.BaseClass
{
public override void DoStuff()
{
// Do stuff.
}
public override void DoOtherStuff()
{
// Do other stuff.
}
}
class TestClass
{
static void Main(string[] args)
{
// Assume singleton is already created here.
BaseClass bc = ManagerClass.CreateBaseClass<DerivedClass>();
// bc.IsRunning should be accessible
// bc.DoStuff() and DoOtherStuff() should not be accessible
}
}
**
Update
**
Okay, so after finding out there was no way to make the delegate work for the abstract class using generics, I tried using interfaces with a factory. This didn't work either, because I was forced to either make the entire BaseClass public, or be unable to call the DoStuff() and DoOtherStuff() from the ManagerClass. And then I realized I don't need a factory at all, because the DerivedClass calls the BaseClass constructor, and I can do all my stuff in there... sort of.
So at the moment I have a wrapper class that contains a BaseClass and a scope class that I can use to store delegates or other members that only the ManagerClass should have access to. The public members can still be accessed publicly, but the ManagerClass now has to go through the wrapper to access the methods.
New Problem
Now the only problem is that I'm storing a wrapper for each instance of BaseClass. Since I only need to store delegates in my BaseClassScope, how can I store the delegate when the BaseClass static constructor is called, and then how can I call the most overriden method using that delegate?
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
ManagerClass.BaseClass[] dc = new DerivedClass[4];
for (int i = 0; i < 4; i++)
{
dc[i] = new DerivedClass();
// Is accessible from outside ManagerClass
dc[i].IsRunning = true;
// Is not accessible from outside ManagerClass
// dc[i].DoStuff();
}
ManagerClass.TestManager();
// Wait for input.
Console.ReadKey(true);
}
}
class ManagerClass
{
static List<BaseClassWrapper> managedList = new List<BaseClassWrapper>();
public static void TestManager()
{
for (int i = 0; i < managedList.Count; i++)
{
// Is accessible from inside ManagerClass
managedList[i].bcs.DoStuff();
managedList[i].bcs.DoOtherStuff();
}
}
class BaseClassScope
{
public Action DoStuff;
public Action DoOtherStuff;
public BaseClassScope(Action ds, Action dos)
{
DoStuff = ds;
DoOtherStuff = dos;
}
}
class BaseClassWrapper
{
public BaseClass bc;
public BaseClassScope bcs;
public BaseClassWrapper(BaseClass bc, BaseClassScope bcs)
{
this.bc = bc;
this.bcs = bcs;
}
}
public abstract class BaseClass
{
public BaseClass()
{
Console.WriteLine("BaseClass()");
var bcs = new BaseClassScope(DoStuff, DoOtherStuff);
var bcw = new BaseClassWrapper(this, bcs);
managedList.Add(bcw);
}
public bool IsRunning { get; set; }
protected virtual void DoStuff()
{
Console.WriteLine("BaseClass.DoStuff()");
}
protected abstract void DoOtherStuff();
}
}
class DerivedClass : ManagerClass.BaseClass
{
public DerivedClass()
{
Console.WriteLine("DerivedClass()");
}
protected override void DoStuff()
{
Console.WriteLine("DerivedClass.DoStuff()");
}
protected override void DoOtherStuff()
{
Console.WriteLine("DerivedClass.DoOtherStuff()");
}
}
I think this is going to be the solution I go with. It uses the curiously recurring template pattern, but it removes the need of all those wrapper classes, AND it doesn't use any reflection.
using System;
using System.Collections.Generic;
namespace testapp2
{
class Program
{
static void Main()
{
ClassA a = ClassA.Instance;
ClassB b = ClassB.Instance;
ManagerClass.TestManager();
Console.ReadKey(true);
}
}
}
class ManagerClass
{
static ManagerClass instance;
static Dictionary<Type, ManagedClass> managedList = new Dictionary<Type, ManagedClass>();
public ManagerClass Instance
{
get
{
if (instance == null)
{
instance = new ManagerClass();
}
return instance;
}
}
ManagerClass()
{
}
public static void TestManager()
{
foreach (var kvp in managedList)
{
kvp.Value.doStuffCallback();
kvp.Value.doOtherStuffCallback();
}
}
public static void CreateManagedClass(Type type, Action doStuffCallback, Action doOtherStuffCallback)
{
managedList.Add(type, new ManagedClass(doStuffCallback, doOtherStuffCallback));
}
public static void DestroyManagedClass(Type type)
{
managedList.Remove(type);
}
class ManagedClass
{
public Action doStuffCallback;
public Action doOtherStuffCallback;
public ManagedClass(Action doStuffCallback, Action doOtherStuffCallback)
{
this.doStuffCallback = doStuffCallback;
this.doOtherStuffCallback = doOtherStuffCallback;
}
}
public abstract class ManagedClassBase<T> where T : class, new()
{
static T instance;
public static T Instance
{
get
{
if (instance == null)
{
instance = new T();
}
return instance;
}
}
protected ManagedClassBase()
{
CreateManagedClass(typeof(T), DoStuff, DoOtherStuff);
}
~ManagedClassBase()
{
instance = null;
}
protected abstract void DoStuff();
protected abstract void DoOtherStuff();
}
}
class ClassA : ManagerClass.ManagedClassBase<ClassA>
{
protected override void DoStuff()
{
Console.WriteLine("ClassA.DoStuff()");
}
protected override void DoOtherStuff()
{
Console.WriteLine("ClassA.DoOtherStuff()");
}
}
class ClassB : ManagerClass.ManagedClassBase<ClassB>
{
protected override void DoStuff()
{
Console.WriteLine("ClassB.DoStuff()");
}
protected override void DoOtherStuff()
{
Console.WriteLine("ClassB.DoOtherStuff()");
}
}
这篇关于如何从封装在管理器类中的基类派生类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!