有没有一种方法可以使类中的某个对象不可由某些代码重新赋值
本文关键字:代码 赋值 新赋值 对象 方法 一种 可以使 有没有 | 更新日期: 2023-09-27 17:59:06
我有一个Windows服务,它会查看dll列表(在设置文件中),将它们全部加载到中,并在每个dll中的自己线程上启动一个特定的方法。这些dll中的每一个都必须继承自一个特定的类(Module类)才能被此服务使用,而该类的一部分是MPI对象,基本上是一个类的实例,它允许dll方法调用方法与服务直接交互。进展如何:
- 服务加载dll
- 使用反射检查是否存在继承Module类的类
- 创建该模块继承类的新实例
- 创建MPI类的新实例。这包含有关哪个模块正在使用它的识别信息
- 将新创建的MPI对象分配给新的Module类
- 启动主模块线程
基本模块类本身是它自己的dll(这样服务和外部dll都可以使用它)。我想做的是让服务能够将一个MPI对象(具有特殊值)分配给新的Module类,但我不希望该类能够更改MPI对象赋值或其中的任何值。对于继承的类为ReadOnly,但可从其他类赋值。我想我不能按照我设置的方式来做这件事,我必须做什么改变才能做到这一点。这可能吗?
MPI在很大程度上类似于主托管服务的API。它处理一些集中的事情,比如错误日志记录。当服务加载一个新模块时,它会为其分配一个ID。当该模块调用MPI.ErrorLog(someStuff)
时,MPI(它引用了主服务内存,因此可以访问实际的错误写入程序)将写入模块ID#此时出现此错误。我希望ID对继承Module的类是私有的,但对主服务不是私有的,这样ID就可以由它来设置。不要说私有变量带有一个设置所有内容的构造函数,因为我不希望Module能够自己创建一个新的MPI对象,并能够改变这些东西。
据我所知,您希望修改不同上下文/用户对单个对象的访问权限。例如,"base"知道get和set访问器,而"module"只知道get访问器。我可以想象这里有两个选项——访问修饰符和接口。
首先,internal
修饰符使成员仅对同一程序集中的文件可见。
public class Mpi
{
private int id;
int Id
{
public get
{
return this.id;
}
internal set
{
this.id = value;
}
}
//...
}
因此,您的"module"将假定这是一个只获取的属性,而您的"base"将能够同时获取和设置。
您的第二个选择是拥有一个只定义get访问器的接口。
public interface IMpi
{
int Id { get; }
}
public class Mpi : IMpi
{
public int Id { get; set; }
}
在此模型中,"基类"使用Mpi
对象,"模块"类使用IMpi
对象。它们是同一个实例,但模块同样不知道Id
属性有一个set方法。
假设您有:
var modules = from file in Directory.GetFiles(path, "*.dll").AsParallel()
from type in Assembly.LoadFile(file).GetTypes().AsParallel()
where !type.IsInterface && typeof(Module).IsAssignableFrom(type)
select (Module)Activator.CreateInstance(type);
然后你声明你的模块基类:
public abstract class Module
{
public abstract Mpi Mpi { get; set; } // to inherit you must implement getter (you don't need it) and setter (what you're asking about)
public abstract void Main(); // to inherit you must implement too
}
使用:
Mpi mpi = new Mpi();
foreach (Module m in modules)
{
m.Mpi = mpi;
m.Main();
}
另一个解决方案。如果基类haы是一个无参数的构造函数,它总是被调用的。在里面,你可以分配一个只能由基类写入的变量:
public abstract class Module
{
protected Module()
{
this.Mpi = new Mpi();
}
protected Mpi Mpi { get; private set; } // getter is visible to children, setter only for class itself
}