我有一个ManagerClass来管理从抽象BaseClass派生的类。我需要它,以便只有ManageClass可以访问BaseClass上的某些方法。我还需要某些方法可以在ManagerClass的范围之外访问。由于C#没有朋友,我将BaseClass封装在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中存储委托,如何在调用BaseClass静态构造函数时存储委托,然后如何使用该委托调用最重写的方法?
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()");
}
}
答案 0 :(得分:1)
所以我认为这样的事情可行。在我编写它时有点复杂,其中一些可能能够被清理,但基本上取决于嵌入式类访问父类的私有静态变量的能力。我没有机会测试它,但我认为这应该达到你想要的效果:
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
}
}
答案 1 :(得分:0)
我仍然在寻找一种没有反思的方法来做到这一点,所以我会留下这个问题,直到有人能弄清楚。目前,这是一个使用反射的解决方案。
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()");
}
}
答案 2 :(得分:0)
我认为这将成为我的解决方案。它使用奇怪的重复模板模式,但它不需要所有这些包装类,并且它不使用任何反射。
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()");
}
}