如何从封装在管理器 class 中的基 class 派生 classes?
How can I derive classes from a base class that is encapsulated in a manager class?
我有一个管理 class 派生自抽象 BaseClass 的类的 ManagerClass。我需要它以便只有 ManageClass 可以访问 BaseClass 上的某些方法。我还需要某些方法可以在 ManagerClass 的范围之外访问。由于 C# 没有朋友,我将 BaseClass 封装在 ManagerClass 中。
问题:
- 无法访问 BaseClass 派生自
- Making BaseClass public,意味着允许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
}
}
**
更新
**
好的,所以在发现无法使用泛型让委托为抽象 class 工作后,我尝试使用工厂接口。这也不起作用,因为我被迫要么创建整个 BaseClass public,要么无法从 ManagerClass 调用 DoStuff() 和 DoOtherStuff()。然后我意识到我根本不需要工厂,因为 DerivedClass 调用 BaseClass 构造函数,我可以在那里做我所有的事情......有点。
所以目前我有一个包装器 class,其中包含一个 BaseClass 和一个范围 class,我可以使用它来存储只有 ManagerClass 应该可以访问的委托或其他成员。 public 成员仍然可以 public 访问,但是 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()");
}
}
所以我认为这样的方法可行。我写的时候有点复杂,其中一些可能可以清理,但基本上取决于嵌入式 class 访问父级私有静态变量的能力。我还没有机会测试它,但我认为这应该能达到你想要的效果:
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()");
}
}
我有一个管理 class 派生自抽象 BaseClass 的类的 ManagerClass。我需要它以便只有 ManageClass 可以访问 BaseClass 上的某些方法。我还需要某些方法可以在 ManagerClass 的范围之外访问。由于 C# 没有朋友,我将 BaseClass 封装在 ManagerClass 中。
问题:
- 无法访问 BaseClass 派生自
- Making BaseClass public,意味着允许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
}
}
**
更新
**
好的,所以在发现无法使用泛型让委托为抽象 class 工作后,我尝试使用工厂接口。这也不起作用,因为我被迫要么创建整个 BaseClass public,要么无法从 ManagerClass 调用 DoStuff() 和 DoOtherStuff()。然后我意识到我根本不需要工厂,因为 DerivedClass 调用 BaseClass 构造函数,我可以在那里做我所有的事情......有点。
所以目前我有一个包装器 class,其中包含一个 BaseClass 和一个范围 class,我可以使用它来存储只有 ManagerClass 应该可以访问的委托或其他成员。 public 成员仍然可以 public 访问,但是 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()");
}
}
所以我认为这样的方法可行。我写的时候有点复杂,其中一些可能可以清理,但基本上取决于嵌入式 class 访问父级私有静态变量的能力。我还没有机会测试它,但我认为这应该能达到你想要的效果:
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()");
}
}