我有一个管理,从一个抽象的BaseClass派生的类一个ManagerClass。 我需要它,以便只有ManageClass可以在BaseClass的访问某些方法。 我还需要某些方法是ManagerClass的范围之外访问。 因为C#没有朋友,我封装ManagerClass内的BaseClass。
问题:
- BaseClass的是无法访问的,从获得
- 制作BaseClass的公众,意味着允许DoStuff()和DoOtherStuff()从ManagerClass,这是我不希望的范围之内调用。
我怎样才能使这项工作?
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
}
}
**
更新
**
好了,所以查不到有没有办法让使用泛型抽象类委托工作之后,我尝试使用接口与一个工厂。 这没有任何工作,因为我被迫要么使整个BaseClass的市民,或无法从ManagerClass调用DoStuff()和DoOtherStuff()。 然后我意识到我并不需要一个工厂可言,因为DerivedClass调用BaseClass的构造函数,我可以做我所有的东西在里面......之类的。
因此,在现阶段,我有一个包含BaseClass的,我也可以用它来存储委托或其他成员只有ManagerClass应该有访问范围类的包装类。 公众成员仍然可以公开访问,但现在ManagerClass要经过包装访问方法。
新问题
现在唯一的问题是,我存储的BaseClass的每个实例的包装。 因为我只需要存储在我的BaseClassScope代表,我怎么能当存储基类的静态构造函数被调用的委托,然后我怎么能叫使用该委托的最覆盖方法?
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()");
}
}
所以我觉得这样的事情可以工作。 它有一个有点令人费解,因为我写的,其中一些可能能够被清理,但基本上取决于嵌入式类来访问父的私有静态变量的能力。 我还没有机会测试它,但我认为这应该达到你想要什么:
public class ManagerClass
{
// This is a singleton class.
static ManagerClass instance;
private static Func<BaseClassFunctionHolder, BaseClass> _createBaseClass;
public static T CreateBaseClass<T>() where T : BaseClass, new()
{
// Create and return a BaseClass.
// Everything in BaseClass should be accessible here.
//example
BaseClassFunctionHolder holder = new BaseClassFunctionHolder();
T baseClass = _createBaseClass(holder);
//access to baseClass methods through holder.DoStuff, and holder.DoOtherStuff
return baseClass;
}
private class BaseClassFunctionHolder
{
public Action DoStuff { get; set; }
public Action DoOtherStuff { get; set; }
}
abstract class BaseClass
{
static BaseClass()
{
_createBaseClass = (holder) => new BaseClass(holder);
}
private BaseClass(BaseClassFunctionHolder holder)
{
holder.DoStuff = DoStuff;
holder.DoOtherStuff = DoOtherStuff;
}
public bool IsRunning { get; set; }
virtual void DoStuff()
{
// Do stuff.
}
abstract void DoOtherStuff();
}
}
public class DerivedClass : ManagerClass.BaseClass
{
override void DoStuff()
{
// Do stuff.
}
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
}
}
我仍然在寻找一种方式来做到这一点没有反思,所以我会离开这个问题的答复,直到有人可以计算出来。 现在,这里是一个使用反射的解决方案。
using System;
using System.Collections.Generic;
using System.Reflection;
class Program
{
static void Main(string[] args)
{
ManagerClass.BaseClass dc = new DerivedClass();
ManagerClass.BaseClass adc = new AnotherDerivedClass();
// Is accessible from outside ManagerClass
dc.IsRunning = true;
// Is not accessible from outside ManagerClass
// dc.DoStuff();
ManagerClass.TestManager();
// Wait for input.
Console.ReadKey(true);
}
}
class ManagerClass
{
static ManagerClass instance;
static List<BaseClass> managedList = new List<BaseClass>();
static MethodInfo doStuffMethod = typeof(BaseClass).GetMethod("DoStuff", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.ExactBinding);
static MethodInfo doOtherStuffMethod = typeof(BaseClass).GetMethod("DoOtherStuff", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.ExactBinding);
public static ManagerClass Instance
{
get
{
if (instance == null)
{
instance = new ManagerClass();
}
return instance;
}
}
public static void TestManager()
{
for (int i = 0; i < managedList.Count; i++)
{
// DoStuff() and DoOtherStuff need to be accessible only from the ManagerClass.
// Invocation of the virtual methods calls the derived methods.
doStuffMethod.Invoke(managedList[i], null);
doOtherStuffMethod.Invoke(managedList[i], null);
}
}
public abstract class BaseClass
{
public BaseClass()
{
Console.WriteLine("BaseClass()");
managedList.Add(this);
// All of ManagerClass fields are accessible from here:
// instance, managedList, etc.
}
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()");
// None of the ManagerClass fields are accessible from classes deriving from BaseClass:
// instance, managedList, etc.
}
protected override void DoStuff()
{
Console.WriteLine("DerivedClass.DoStuff()");
}
protected override void DoOtherStuff()
{
Console.WriteLine("DerivedClass.DoOtherStuff()");
}
}
class AnotherDerivedClass : ManagerClass.BaseClass
{
public AnotherDerivedClass()
{
Console.WriteLine("AnotherDerivedClass()");
}
protected override void DoStuff()
{
Console.WriteLine("AnotherDerivedClass.DoStuff()");
}
protected override void DoOtherStuff()
{
Console.WriteLine("AnotherDerivedClass.DoOtherStuff()");
}
}
我认为这将是解决我一起去。 它采用了奇异递归模板模式,但它会删除所有的包装类的需求,它不使用任何反映。
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()");
}
}
文章来源: How can I derive classes from a base class that is encapsulated in a manager class?