实际上我只想使用普通的继承功能
问题是,我的一些方法是静态的,因此它们无法正常访问继承的属性。
此外,我无法将任何内容传递给静态方法(如对象的实例),因为它们被"外部触发器调用"。
另一方面,我不需要多个实例,这意味着单身就好了。
让我一步一步向你解释我的情况:
(或者只是跳转到第一个代码示例以查看MCV示例)
我使用库Harmony来修补现有程序集的方法。 修补方法必须是静态的,并由"钩子"图书馆 我为游戏添加了新的玩家升级。对于我要修补的每次升级,我创建了一个包含成员的类,如名称,描述,图像...... 一次升级必须只修补一次,因此这里的解决方案是使静态变为静止 但是......
因为这些升级共享了许多常见的成员和方法,所以我创建了一个BaseUpgrade类并从中派生出来。
现在,每个特定的实现都可以将它们的值分配给公共字段,如名称,描述......并继承其余的(使用成员的方法)。
然而,成员无法通过静态修补方法访问。为此,我可以使用单身人士
我想继承所有Singleton的东西,使它成为通用的。这样只有基类具有所有Singeton代码
一种方法是这种解决方案:https://stackoverflow.com/a/16865465
但是......
我需要拥有基类的集合并在字典中使用它们(作为键和值)。但这似乎与泛型类无关 我找到了Collection of generic types,但我被卡住了。我不知道合并这个是否真的有效。至少它会使事情变得更复杂。
那会有用吗?对我的问题可能有一个更简单的方法吗?
using System;
using System.Collections.Generic;
namespace Using_Singleton
{
// This is the version trying to incorperate the inheritable singleton
class Base<T> where T : Base<T>, new()
{
#region Singleton stuff
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
_instance = new T();
return _instance;
}
set => _instance = value;
}
#endregion
public string name; // Should be accessible by the derived class' static methods
public string desc;
protected Base()
{
name = "Base";
}
public void printName()
{
Console.WriteLine(name);
}
}
class FirstChild : Base<FirstChild>
{
public int number; // Should be accessible by the class' static methods
public FirstChild()
{
name = "The first child";
number = 7;
}
public static void StaticMethod_FirstChild()
{
Console.WriteLine("StaticMethod_FirstChild: I can access all member variables! :-)");
Console.WriteLine("Name: " + Instance.name + ", Number: " + Instance.number); // This is now working
}
}
class SecondChild : Base<SecondChild>
{
public float myfloat;
public SecondChild()
{
name = "The second child";
myfloat = 0.3f;
}
public static void StaticMethod_SecondChild()
{
Console.WriteLine("StaticMethod_SecondChild: I can access all member variables! :-)");
Console.WriteLine("Name 2x: " + Instance.name + " " + Instance.name); // This is now working
}
}
class Manager // Manages instances/singletons which derive from "Base" by using a collection of the Base class
{
//Dictionary<string, Base> itemDict; // ******* This is now broken
public Manager()
{
//itemDict = new Dictionary<string, Base>();
//Base addItem;
//addItem = new FirstChild();
//itemDict.Add(addItem.GetType().Name, addItem);
//addItem = new SecondChild();
//itemDict.Add(addItem.GetType().Name, addItem);
// Simulating the external call of one static method
SecondChild.StaticMethod_SecondChild();
Console.WriteLine();
}
public void DoSomething()
{
//foreach (var item in itemDict)
//{
// item.Value.printName();
//}
}
}
class Program
{
static void Main(string[] args)
{
Manager manager = new Manager();
manager.DoSomething();
Console.ReadLine();
}
}
}
using System;
using System.Collections.Generic;
namespace Using_Singleton
{
// This is the version trying to incorperate the inheritable singleton
class Base<T> where T : Base<T>, new()
{
#region Singleton stuff
private static T _instance;
public static T Instance
{
get
{
if (_instance == null)
_instance = new T();
return _instance;
}
set => _instance = value;
}
#endregion
public string name; // Should be accessible by the derived class' static methods
public string desc;
protected Base()
{
name = "Base";
}
public void printName()
{
Console.WriteLine(name);
}
}
class FirstChild : Base<FirstChild>
{
public int number; // Should be accessible by the class' static methods
public FirstChild()
{
name = "The first child";
number = 7;
}
public static void StaticMethod_FirstChild()
{
Console.WriteLine("StaticMethod_FirstChild: I can access all member variables! :-)");
Console.WriteLine("Name: " + Instance.name + ", Number: " + Instance.number); // This is now working
}
}
class SecondChild : Base<SecondChild>
{
public float myfloat;
public SecondChild()
{
name = "The second child";
myfloat = 0.3f;
}
public static void StaticMethod_SecondChild()
{
Console.WriteLine("StaticMethod_SecondChild: I can access all member variables! :-)");
Console.WriteLine("Name 2x: " + Instance.name + " " + Instance.name); // This is now working
}
}
class Manager // Manages instances/singletons which derive from "Base" by using a collection of the Base class
{
//Dictionary<string, Base> itemDict; // ******* This is now broken
public Manager()
{
//itemDict = new Dictionary<string, Base>();
//Base addItem;
//addItem = new FirstChild();
//itemDict.Add(addItem.GetType().Name, addItem);
//addItem = new SecondChild();
//itemDict.Add(addItem.GetType().Name, addItem);
// Simulating the external call of one static method
SecondChild.StaticMethod_SecondChild();
Console.WriteLine();
}
public void DoSomething()
{
//foreach (var item in itemDict)
//{
// item.Value.printName();
//}
}
}
class Program
{
static void Main(string[] args)
{
Manager manager = new Manager();
manager.DoSomething();
Console.ReadLine();
}
}
}
答案 0 :(得分:1)
在向小例子添加可继承单例后,我尝试添加对通用集合的支持,如suggested by Jon Saunders。
基本上将接口或类“置于”单例类(单例类继承它)之上,并将其用于集合或方法参数。
在这个新的非泛型类中,我已经放了所有的字段和方法。顶级非泛型类和泛型类的构造函数受到保护,因此无法实例化它们。
using System;
using System.Collections.Generic;
namespace Using_Singleton_And_GenericCollection
{
// This is the version trying to incorperate the inheritable singleton and a generic collection
abstract class NonGenericBase // Adding this (class or interface) make the use of collections possible.
{
public string name;
public string desc;
public void printName()
{
Console.WriteLine("\t" + name);
}
protected NonGenericBase() { }
}
class Base<T> : NonGenericBase where T : Base<T>, new()
{
#region Singleton stuff
protected static T _instance;
public static T Instance
{
get
{
if (_instance == null)
_instance = new T();
return _instance;
}
set => _instance = value;
}
#endregion
//public string name; // Moved to parent
//public string desc;
protected Base()
{
name = "Base";
}
}
class FirstChild : Base<FirstChild>
{
public int number; // Should be accessible by the class' static methods
public FirstChild()
{
name = "The first child";
number = 7;
}
public static void StaticMethod_FirstChild()
{
Console.WriteLine("\tStaticMethod_FirstChild: I can access all member variables! :-)");
Console.WriteLine("\tName: " + Instance.name + ", Number: " + Instance.number); // This is now working
}
}
class SecondChild : Base<SecondChild>
{
public float myfloat;
public SecondChild()
{
name = "The second child";
myfloat = 0.3f;
}
public static void StaticMethod_SecondChild()
{
Console.WriteLine("\tStaticMethod_SecondChild: I can access all member variables! :-)");
Console.WriteLine("\tName 2x: " + Instance.name + ", " + Instance.name); // This is now working
}
}
class Manager // Manages instances/singletons which derive from "Base" by using a collection of the Base class
{
public Dictionary<string, NonGenericBase> itemDict;
public Manager()
{
itemDict = new Dictionary<string, NonGenericBase>();
NonGenericBase addItem;
addItem = FirstChild.Instance;
itemDict.Add(addItem.GetType().Name, addItem);
addItem = SecondChild.Instance;
itemDict.Add(addItem.GetType().Name, addItem);
}
public void DoSomething()
{
foreach (var item in itemDict)
{
item.Value.printName();
}
Console.WriteLine();
}
}
class Program
{
static void Main(string[] args)
{
var sec = new SecondChild();
Console.WriteLine("Access Singletons");
Manager manager = new Manager();
manager.DoSomething();
Console.WriteLine("Change Singletons");
manager.itemDict[nameof(FirstChild)].name = "first name changed";
SecondChild.Instance.name = "second name changed too";
manager.DoSomething();
Console.WriteLine("Create and change a non-Singleton instance of FirstChild");
var initItem = new FirstChild();
initItem.printName();
initItem.name = "Non-Singleton name changed";
initItem.printName();
Console.WriteLine();
Console.WriteLine("Access Singletons");
manager.DoSomething();
Console.WriteLine("Call static method of FirstChild");
FirstChild.StaticMethod_FirstChild(); //Simulating the external call of one static method
Console.WriteLine();
Console.ReadKey();
}
}
}
Access Singletons
The first child
The second child
Change Singletons
first name changed
second name changed too
Create and change a non-Singleton instance of FirstChild
The first child
Non-Singleton name changed
Access Singletons
first name changed
second name changed too
Call static method of FirstChild
StaticMethod_FirstChild: I can access all member variables! :-)
Name: first name changed, Number: 7
因为这里有“new()”
class Base<T> : NonGenericBase where T : Base<T>, new()
特定子类的构造函数需要公开。这意味着单身人士不会被强制执行,而是“只是”一个选项(请参阅输出示例)。
BTownTKD states that in his answer他说明了这个事实以及他试图通过反映手动调用私人构造函数来解决这个问题的链接:Singleton.cs
感谢您为此问题做了MCV示例,并以极低的复杂性再次尝试,我自己找到了解决方案。
所以这里的质疑过程和改进我的初始帖子帮助了我。 : - )