如何使用参数化构造函数实现保存/加载接口?
我知道接口不能定义构造函数。这是我希望我能做的:
public interface SavableObject {
void Save(ObjectSaver saver);
SavableObject(ObjectLoader loader); //This, obviously, doesn't work
}
//Loading an object inside ObjectLoader:
T LoadObject<T>() where T : SavableObject {
return (T)Activator.CreateInstance(typeof(T), this);
}
如果我取出不起作用的行,并且在尝试加载时只会出现运行时错误(或者可能保存,如果我在其中放置断言)对象(如果没有构造函数)。我只是想知道是否有任何方法要求一个类具有可与激活器一起使用的特定构造函数。我可以以某种方式使用自定义属性,并要求该属性位于类中吗?或者我必须依赖运行时检查来加载和保存数据?
我知道我可以有一个无参数构造函数和一个 Load(ObjectLoader) 方法,但我不一定希望有一个无参数构造函数可用于其他目的。
I know interfaces cannot define constructors. Here's what I wish I could do:
public interface SavableObject {
void Save(ObjectSaver saver);
SavableObject(ObjectLoader loader); //This, obviously, doesn't work
}
//Loading an object inside ObjectLoader:
T LoadObject<T>() where T : SavableObject {
return (T)Activator.CreateInstance(typeof(T), this);
}
And I could do this if I took out the line that didn't work, and there would just be a runtime error when trying to load (or possibly save, if I put an assert in there) the object if it didn't have the constructor. I'm just wondering if there's any way to require a class to have a particular constructor that can be used with the Activator. Can I use a custom attribute somehow, and require that attribute to be on the class? Or must I rely on runtime checks to load and save data?
I know I could have a parameterless constructor and a Load(ObjectLoader)
method but I don't necessarily want to have a parameterless constructor available to abuse for other purposes.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
ISerialized 怎么样?
what about ISerializable?
简而言之,我建议您像大多数工厂一样使用
泛型
。然而,你似乎已经把它颠倒过来了。 该类正在做工厂必须做的事情。所以我认为将工厂传递给实体本身并不是一个好主意,这是您在设计。
In brief I suggest you use
generics
as most factories do.However, you seem to have turned it on it head. The class is doing what factory must do. So I do not think it is such a good idea to pass the factory to the entity itself and that is part of the problem you are experiencing in the design.
如果您不害怕使用反射,就像您所展示的 Activator 一样,您可以做一些我倾向于使用的小技巧:
我不知道这是否适合您,但是当我需要反序列化相当大的游戏状态时,我使用了该方法,并且速度非常快,尽管所有这些反射(由于多种原因,我不想使用内置序列化)方法和工厂模式不会这样做,所以我倾向于将此方法视为在其他方法失败时可能有用的方法,另一方面,如果可以的话 - 为了简单起见,我可能会使用内置序列化)。
If you are not afraid of using Reflection, like Activator that you have shown, you can do little trick I tend to use:
I don't know if this will work for you, but I used that method when I needed to deserialize pretty big game state and it was pretty fast, eventhough all this reflection (for many reasons I did not wanted to use built-in serialization methods and Factory Pattern wouldn't do, so I tend to treat this method as something that may be useful if other methods fail, on the other hand, if I could - I would probably use built-in serialization for simplicity).
如何在您的界面上添加属性:
然后在您的工厂中:
How about adding a property on your interface:
Then in your factory:
根据您的问题和评论。
我认为你应该在运行时使用反射来完成它。
将构造函数和接口结合起来从其核心来看是不合逻辑的。接口是关于具体实例可以做什么,而不是如何初始化它。这只能使用抽象类来实现。
也许使用工厂来创建类的实例?
另外,我认为您无法获得比默认 ISerialized 实现更好的速度。除非您是 .NET GURU 并且有多年的时间。
Based on your question and comments.
I think you should do it at runtime using reflection.
Combining constructors and interfaces is ilogical from its core. Interface is about what concrete instance can do, not how to initialize it. This can only be achived using abstract class.
Maybe using factory to create instance of the class?
Also I don't think you can get better speed than default ISerializable implementation. Unless you are .NET GURU and have years of time for it.
简短的回答:我想这是不可能的。我没有可以使用任何属性或概括来要求类上有特定类型的构造函数。
Short answer: It's not possible, I guess. There are no attributes or generalizations I can use to require a specific kind of constructor on a class.