I have some problems cloning an object hierarchie. It's a toolkit for modelling applications, the toolbox contains class instances as prototypes. But I'm having a hard time cloning these :)
The following code shows the problem:
public abstract class Shape {
protected List<UIElement> elements;
private Canvas canvas;
...
public Canvas getCanvas() { ... };
}
public class MovableShape : Shape {
protected ... propertyA;
private ... propertyXY;
...
}
public abstract class AbstractLayout : MovableShape, ... {
...
}
public class SomeLayoutClass : AbstractLayout, ... {
...
}
public class AContainingClass {
SomeLayoutClass Layout { get; set; }
...
}
When I insert an object of AContainingClass into my project worksheet, it should be cloned. So far I tried manual cloning (which fails because of the private fields in the base classes) and binary serialization (BinaryFormatter and MemoryStreams).
The first approach lacks a way to call the base.clone() method (or am I wrong?), the latter does not work because UIElements aren't [Serializable].
Note: it must be a deep copy!
Any ideas? Thanks!
UPDATE
Just to clarify my manual cloning approach:
If each class has it's own Clone method, how to call the Clone method of the base class?
public class Shape { // not abstract any more
...
public Shape Clone() {
Shape clone = new Shape() { PropertyA = this.PropertyA, ... };
...do some XamlWriter things to clone UIElements...
return clone;
}
}
public class MovableShape : Shape {
...
public MovableShape Clone() {
// how to call base.Clone???
// this would be required because I have no access to the private fields!
}
}
And here the function for it:
public T XamlClone<T>(T source)
{
string savedObject = System.Windows.Markup.XamlWriter.Save(source);
// Load the XamlObject
StringReader stringReader = new StringReader(savedObject);
System.Xml.XmlReader xmlReader = System.Xml.XmlReader.Create(stringReader);
T target = (T)System.Windows.Markup.XamlReader.Load(xmlReader);
return target;
}
If you are attempting to clone UIElements, use the XamlWriter to save to a string, though no method of cloning is foolproof. You then use XamlReader to load a copy. You could still run into issues. Things like handlers not being copied, x:Name being duplicated, etc. But for simple elements like Grid or Brush, it works great.
Edit 1: There is no generic way to clone anything, however:
1) If a clone function is written correctly, it will call the base Clone for you, and copy the base class stuff, too. If it isn't written correctly calling the base Clone won't help much, though you can call a private method this way.
2) If you have to, you can use Reflection to copy pretty much anything, even click handlers, from an old object to a new object.
3) XamlWriter and XamlReader will copy and instantiate heirarchies of objects, just minus certain properties.
Edit 2: Here's a common cloning design pattern I use in my class hierarchies. Assume base class shape, derived class circle:
protected Circle(Circle t)
{
CopyFrom(t);
}
public override object Clone()
{
return new Circle(this);
}
protected void CopyFrom(Circle t)
{
// Ensure we have something to copy which is also not a self-reference
if (t == null || object.ReferenceEquals(t, this))
return;
// Base
base.CopyFrom((Shape)t);
// Derived
Diameter = t.Diameter;
}
Haven't tried it myself, but XamlWriter looks promising.
Related
I have a business entities as below,
class Class1
{
List<Class2> classes = new List<Class2>();
public IEnumerable<Class2> Classes { get { return classes.AsEnumrable(); }
public void AddClass(Class2 cls)
{
classes.Add(cls);
}
}
class Class2
{
public string Property { get; set; }
}
My business logic requires that once a Class2 instance is added using the AddClass method to the top of the Classes list in Class1, no one should be able to edit the properties of the Class2 instances added previously to the list, only the last item in the list could be edited. How do I do this?
I have tried IReadOnlyList, but it appears that it is concerned with making the list structure itself uneditable without preventing the edit of its items' content.
It's not a container's job to dictate the behavior of its items. A container is just that - an object that contains other objects. An IReadOnlyList is a container whose items cannot be modified. But the items within it are jsut Class2 instances - there's nothing that the container can do to prevent them from being edited.
Consider this:
myReadOnlyCollection[0].Property = "blah";
var firstItem = myReadOnlyCollection[0];
firstItem.Property = "blah";
Should this be legal in your scenario? What's the difference between the two? firstItem is simply an instance of Class2 that has no idea it was once inside a read-only collection.
What you need is for Class2 itself to be immutable. That's up to the class, not the container. Read up on immutability, which is an important concept to grasp, and implement Class2 accordingly. If you need a regular, mutable Class2 to change its behavior, perhaps add a ToImmutable() method to it which returns a different item, without a setter.
Why are you exposing the IReadOnlyCollection. Once you have exposed the objects, the objects themselves have to be immutable.
Why not just expose the only object that you want to expose?
private IEnumerable<Class2> Classes { get { return classes; }
public Class2 Class2Instance { get { return classes.Last(); } }
I can only see three options. One is to alter Class2 to make it lockable and then lock it once it's added to your list...
class Class1 {
List<Class2> classes = new List<Class2>();
public IEnumerable<Class2> Classes {
get { return classes.AsEnumrable();
}
public void AddClass(Class2 cls) {
cls.Lock();
classes.Add(cls);
}
}
class Class2 {
private string _property;
private bool _locked;
public string Property {
get { return _property; }
set {
if(_locked) throw new AccessViolationException();
_property = value;
}
}
public void Lock() {
_locked = true;
}
}
Another option is to only return the values of the list objects instead of the objects themselves...
class Class1 {
List<Class2> classes = new List<Class2>();
public IEnumerable<string> Values {
get { return classes.Select(cls => cls.Property); }
}
public void AddClass(Class2 cls) {
classes.Add(cls);
}
}
In this second method, anything other than a single value and you'll need to either return a tuple. Alternately, you could create a specific container for Class2 that exposes the values as read-only...
class Class2ReadOnly {
private Class2 _master;
public Class2ReadOnly(Class2 master) {
_master = master;
}
public string Property {
get { return _master.Property; }
}
}
class Class1 {
List<Class2ReadOnly> classes = new List<Class2ReadOnly>();
public IEnumerable<Class2ReadOnly> Classes {
get { return classes.AsEnumerable(); }
}
public void AddClass(Class2 cls) {
classes.Add(new Class2ReadOnly(cls));
}
}
I know it is an old problem, however I faced the same issue today.
Background: I want to store data in my application, e.g. users can set their custom objects in the project and the Undo-redo mechanism must be adapted to handle batched data storing.
My approach:
I created some interfaces, and I made a wrapper for the collection I don't want the users to modify.
public class Repository : IRepository
{
// These items still can be changed via Items[0].CustomProperty = "asd"
public readonly List<CustomItem> Items { get; }
private readonly List<CustomItem> m_Originaltems;
//However, when I create RepositoryObject, I create a shadow copy of the Items collection
public Repository(List<CustomItem> items)
{
items.ForEach((item) =>
{
// By cloning an item you can make sure that any change to it can be easily discarded
Items.Add((CustomItem)item.Clone());
});
// As a private field we can manage the original collection without taking into account any unintended modification
m_OriginalItems = items;
}
// Adding a new item works with the original collection
public void AddItem(CustomItem item)
{
m_OriginalItems.Add(item);
}
// Of course you have to implement all the necessary methods you want to use (e.g. Replace, Remove, Insert and so on)
}
Pros:
Using this approach you basically just wraps the collection into a custom object. The only thing you expect from the user side is to have ICloneable interface implemented.
If you want, you can make your wrapper generic as well, and give a constraint like where T : ICloneable
Cons:
If you add new items, you won't know about them by checking the Items property. A workaround can be done by creating a copy of the collection whenever Items.get() is called. It is up to you and your requirements.
I meant something like this:
public class Repository : IRepository
{
public List<CustomItem> Items => m_OriginalItems.Select(item => (CustomItem)item.Clone()).ToList();
private readonly List<CustomItem> m_Originaltems;
public Repository(List<CustomItem> items)
{
m_OriginalItems = items;
}
public void AddItem(CustomItem item)
{
m_OriginalItems.Add(item);
}
// Of course you still have to implement all the necessary methods you want to use (e.g. Replace, Count, and so on)
}
As other said, it is not the collections job to dictate if (and how) you access it's elements. I do see ways around this:
Exceptions & references:
Modify Class2 so it can take a reference to Class1. If the reference is set, throw excetpions on all setters. Modify Class1.AddClass to set that property.
A softer version of this would be a "read only" property on Class2, that all other code has to check.
Readonly Properties & Constructors:
Just always give Class2 readonly properties (private set). If you want to define the property values, you have to do that in the constructor (which has proper Arguments). This pattern is used heavily by the Exception classes.
Inheritance Shenanigans:
Make Multiple Class2 versions in an inheritance chain, so that that Class2Writebale can be cast to a Class2ReadOnly.
Accept the wrong Y:
You might have stuck yourself into a XY problem: https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem
If so go a step back to fix it.
I am trying to make use of the MVC Pattern in Unity. I am a programming beginner.
Traps and moving Platforms use the same code so i created a base for them. I divide the code into "Data"-class and "Method"-class.
Both objects move to Point A, then to Point B, back to Point A and so on..
Point A and Point B got a trigger, to change the Movementdirection of the Platform/Trap.
The base class holds the data. The subclass gets the data and fills the base data. In the base class i have the object:
public virtual GameObject MovingObject { get { return null; } }
The subclass overrides the property returning null to make it return the right object. I try it this way:
[SerializeField]
private GameObject movingObject;
public override GameObject MovingObject { get { return movingObject; } }
The private variable is set in the Editor and sets the value to the property. This property gives the information to the base class. The problem is that i get null references and I do not know how to fix that. The base class does not return an object. The information get lost on their way to the base...
Is my logic wrong?
If you need to see the whole structure of these six classes you can look it up on
https://github.com/Garzec/MidnightFeast/tree/master/Assets/Scripts/MovingObjects
Sorry, i did not want to post all lines of code and unrelevant stuff :)
I looked at your code. Assuming you will never need an instance of just a "MovingObjectsController" this looks like you need an abstract class as your base class. An abstract class cannot be instantiated, but it can require a child class (subclass) to implement abstract members, removing the need to return null in the parent. For example, you would define your controller as :
public abstract class MovingObjectsController
{
protected abstract MovingObjectsData Data { get; }
}
public class PlatformController : MovingObjectsController
{
private MovingObjectsData data;
public PlatformController()
{
this.data = new MovingObjectsData(); //This being whatever data is specific to this object
}
protected override MovingObjectsData Data {
get
{
return data;
}
}
}
This way the child is required to implement whatever the parent needs, but the parent isn't required to provide a default implementation that doesn't make sense.
I have two classes that I'd like to keep in separate files.
namespace GridSystem
{
public class Grid
{
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
}
namespace GridSystem
{
public class GridItem
{
public void InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
}
How do I ensure no other classes are allowed to call InformAddedToGrid?
I'm trying to emulate Actionscript namespaces, which can be used on a method, in place of public, private, internal, etc. It doesn't exactly protect the method, but forces an extra step of including the namespace before the method can be accessed. Is there an alternative approach to this in C#?
If GridItem itself can be hidden from the outside world as well I would consider putting GridItem inside Grid as a nested class. That way it won't be visible outside of the class
http://www.codeproject.com/Articles/20628/A-Tutorial-on-Nested-Classes-in-C
Not that you should do this, you should do what TGH suggests, have a public interface for GridItem, and have gridItem nested in Grid (then have a factory method on Grid to create Items and use partial Grid class to have them in separate files).
Because there isn't a way of having friend methods ( you can do friend classes through InternalsVisibleToAttribute )
You COULD do this ( but don't... )
public partial class Grid
{
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
public class GridItem
{
public void InformAddedToGrid()
{
if (new StackTrace().GetFrame(1).GetMethod().DeclaringType !=
typeof(Grid)) throw new Exception("Tantrum!");
Console.WriteLine("Grid called in...");
}
}
then
var g = new Grid();
g.AddItem(new GridItem()); // works
new GridItem().InformAddedToGrid(); // throws a tantrum...
A really ugly answer would be to make it private and use reflection.
Another ugly answer would be to make it throw an exception if the caller is wrong.
Both of these are much slower to execute than a normal call also.
I don't think there's a good answer. C# doesn't have friends.
IMHO the answer is simple: access modifiers are just there to remind the programmer of the intent of how public/private a class should be. Through reflection you can lift those barriers.
The usage you make of a class is all in your hands: if your class is meant to only be used in one place, make it so. If anything, if a class has a special way of being used, document it - put it in the XML comments.
That said, in this specific example I'd believe since the GridItem doesn't add itself to the grid, it's not its job to notify about it (what if "I've not been added to the grid"?). I think InformAddedToGrid belongs somewhere in your Grid class as a private method, where there's a concept of adding an item... assuming that's what AddItem(GridItem) really does.
You can do it as TGH suggested, with nested classes, except the other way around. Nest Grid within GridItem and make InformAddedToGrid private. Here I use a nested base class so the public API can remain the same. Note that no one outside of your assembly can inherit from GridBase because the constructor is internal.
public class GridItem
{
public class GridBase
{
internal GridBase() { }
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
private void InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
public class Grid : GridItem.GridBase { }
Another option is to have GridItem explicitly implement an internal interface. This way no one outside of your assembly can use the interface by name and therefore cannot call InformAddedToGrid.
public class Grid
{
public void AddItem(GridItem item)
{
((IGridInformer)item).InformAddedToGrid();
}
}
public class GridItem : IGridInformer
{
void IGridInformer.InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
internal interface IGridInformer
{
void InformAddedToGrid();
}
C#. I have a base class called FileProcessor:
class FileProcessor {
public Path {get {return m_sPath;}}
public FileProcessor(string path)
{
m_sPath = path;
}
public virtual Process() {}
protected string m_sath;
}
Now I'd like to create to other classes ExcelProcessor & PDFProcessor:
class Excelprocessor: FileProcessor
{
public void ProcessFile()
{
//do different stuff from PDFProcessor
}
}
Same for PDFProcessor, a file is Excel if Path ends with ".xlsx" and pdf if it ends with ".pdf". I could have a ProcessingManager class:
class ProcessingManager
{
public void AddProcessJob(string path)
{
m_list.Add(Path;)
}
public ProcessingManager()
{
m_list = new BlockingQueue();
m_thread = new Thread(ThreadFunc);
m_thread.Start(this);
}
public static void ThreadFunc(var param) //this is a thread func
{
ProcessingManager _this = (ProcessingManager )var;
while(some_condition) {
string fPath= _this.m_list.Dequeue();
if(fPath.EndsWith(".pdf")) {
new PDFProcessor().Process();
}
if(fPath.EndsWith(".xlsx")) {
new ExcelProcessor().Process();
}
}
}
protected BlockingQueue m_list;
protected Thread m_thread;
}
I am trying to make this as modular as possible, let's suppose for example that I would like to add a ".doc" processing, I'd have to do a check inside the manager and implement another DOCProcessor.
How could I do this without the modification of ProcessingManager? and I really don't know if my manager is ok enough, please tell me all your suggestions on this.
I'm not really aware of your problem but I'll try to give it a shot.
You could be using the Factory pattern.
class FileProcessorFactory {
public FileProcessor getFileProcessor(string extension){
switch (extension){
case ".pdf":
return new PdfFileProcessor();
case ".xls":
return new ExcelFileProcessor();
}
}
}
class IFileProcessor{
public Object processFile(Stream inputFile);
}
class PdfFileProcessor : IFileProcessor {
public Object processFile(Stream inputFile){
// do things with your inputFile
}
}
class ExcelFileProcessor : IFileProcessor {
public Object processFile(Stream inputFile){
// do things with your inputFile
}
}
This should make sure you are using the FileProcessorFactory to get the correct processor, and the IFileProcessor will make sure you're not implementing different things for each processor.
and implement another DOCProcessor
Just add a new case to the FileProcessorFactory, and a new class which implements the interface IFileProcessor called DocFileProcessor.
You could decorate your processors with custom attributes like this:
[FileProcessorExtension(".doc")]
public class DocProcessor()
{
}
Then your processing manager could find the processor whose FileProcessorExtension property matches your extension, and instantiate it reflexively.
I agree with Highmastdon, his factory is a good solution. The core idea is not to have any FileProcessor implementation reference in your ProcessingManager anymore, only a reference to IFileProcessor interface, thus ProcessingManager does not know which type of file it deals with, it just knows it is an IFileProcessor which implements processFile(Stream inputFile).
In the long run, you'll just have to write new FileProcessor implementations, and voila. ProcessingManager does not change over time.
Use one more method called CanHandle for example:
abstract class FileProcessor
{
public FileProcessor()
{
}
public abstract Process(string path);
public abstract bool CanHandle(string path);
}
With excel file, you can implement CanHandle as below:
class Excelprocessor: FileProcessor
{
public override void Process(string path)
{
}
public override bool CanHandle(string path)
{
return path.EndsWith(".xlsx");
}
}
In ProcessingManager, you need a list of processor which you can add in runtime by method RegisterProcessor:
class ProcessingManager
{
private List<FileProcessor> _processors;
public void RegisterProcessor(FileProcessor processor)
{
_processors.Add(processor)
}
....
So LINQ can be used in here to find appropriate processor:
while(some_condition)
{
string fPath= _this.m_list.Dequeue();
var proccessor = _processors.SingleOrDefault(p => p.CanHandle(fPath));
if (proccessor != null)
proccessor.Process(proccessor);
}
If you want to add more processor, just define and add it into ProcessingManager by using
RegisterProcessor method. You also don't change any code from other classes even FileProcessorFactory like #Highmastdon's answer.
You could use the Factory pattern (a good choice)
In Factory pattern there is the possibility not to change the existing code (Follow SOLID Principle).
In future if a new Doc file support is to be added, you could use the concept of Dictionaries. (instead of modifying the switch statement)
//Some Abstract Code to get you started (Its 2 am... not a good time to give a working code)
1. Define a new dictionary with {FileType, IFileProcessor)
2. Add to the dictionary the available classes.
3. Tomorrow if you come across a new requirement simply do this.
Dictionary.Add(FileType.Docx, new DocFileProcessor());
4. Tryparse an enum for a userinput value.
5. Get the enum instance and then get that object that does your work!
Otherwise an option: It is better to go with MEF (Managed Extensibility Framework!)
That way, you dynamically discover the classes.
For example if the support for .doc needs to be implemented you could use something like below:
Export[typeof(IFileProcessor)]
class DocFileProcessor : IFileProcessor
{
DocFileProcessor(FileType type);
/// Implement the functionality if Document type is .docx in processFile() here
}
Advantages of this method:
Your DocFileProcessor class is identified automatically since it implements IFileProcessor
Application is always Extensible. (You do an importOnce of all parts, get the matching parts and Execute.. Its that simple!)
I'm currently working on a C# program that creates a List, of object Task, the object Task is a base class and many other inherit from it. What I want to is compare the type of one of the object within said list to see which form should be opened in order to edit it.
This is the code I have already created.
private void itemEdit_Click(object sender, EventArgs e)
{
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
if(checkTask.GetType is Note)
{
noteBuilder editNote = new noteBuilder(todoList);
editNote.Show();
}
else if(checkTask.GetType is extendedTask)
{
extendedTaskBuilder editTask = new extendedTaskBuilder(todoList);
editTask.Show();
}
else if(checkTask.GetType is Reminder)
{
reminderBuilder editReminder = new reminderBuilder(todoList);
editReminder.Show();
}
else if (checkTask.GetType is Appointment)
{
appointmentBuilder editAppointment = new appointmentBuilder(todoList);
editAppointment.Show();
}
}
On a secondary note would it be easier if instead of passing the list between the forms and generating a new object of the form that display information that I instead pass a single object between forms and just update the form every time a new element is added to the list.
Many thanks
Have you tried checking like this:
if (checkTask is Note)
{
}
...
Have you considered creating a base class for all types you are now switching between and call a virtual (abstract) method?
Put all code now in the if in the overridden abstract method.
Advantages:
- The intelligence of the switch is within the classes where it belongs.
- When a new type is added you get a compiler error to also add this feature to the new type.
I suggest that instead of doing that series of ‘if’ clauses, you use inheritance to achieve what ou need. First you create a virtual method in your base class. A virtual method means it won't have any implementation in the base class, only the declaration:
public class Task
{
(...)
public virtual void ShowEditForm(IList todoList);
(...)
}
Then you create the child class methods (I'm assuming the todoList object is a IList, but just change it if it is not).
public class Note: Task
{
(...)
public override void ShowEditForm(IList todoList)
{
(new noteBuilder(taskToEdit)).Show();
}
(...)
}
public class Reminder: Task
{
(...)
public override void ShowEditForm(IList todoList)
{
(new reminderBuilder(taskToEdit)).Show();
}
(...)
}
I didn't write all the classes, but I think you've got the idea. To call the method, you just call the method from Task class, and the right method will be executed:
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
checkTask.ShowEditForm(todoList);
This way, when you want to create new types of Task, you just have to create the child class, with the proper method, and the inheritance system will do the rest.
One more thing, the override keyword in the child method declaration is important, because it says to the compiler that this method should be called even if you call it from the BaseClass.
First, to your second note. What you are talking about doing is having a global object that all forms refer to in some parent. That can work, however you will need to make sure there is some mechanism in place that makes sure all of the forms are synchronized when one changes, and this can get messy and a bit of a mess to maintain. I am not necessarily advocating against it per say, but just adding words of caution when considering it :)
As to your posted code, it would probably be better to turn this into a Strategy Pattern approach, where all forms inherit from a base class/interface which has a Show method. Then all you need to do is call checkTask.Show(todoList);. If you do not want that coming from the Task, then you could have your forms all inherit from the above base and you could use a factory pattern that takes in the Task and list and returns the appropriate form on which you simply call form.Show();
Code like this is difficult to maintain, you are probably better off abstracting this out, like so (assuming Task is not the one included in .net):
public interface IBuilder
{
void Show();
}
public abstract class Task
{
// ...
public abstract IBuilder GetBuilder(TaskList todoList);
// ...
}
public class Note : Task
{
public override IBuilder GetBuilder(TaskList todoList)
{
return new noteBuilder(todoList);
}
// ...
}
// etc.
private void itemEdit_Click(object sender, EventArgs e)
{
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
IBuilder builder = checkTask.GetBuilder(todoList);
builder.Show();
}
Alternately, you can use an injection pattern:
public abstract class Task
{
protected Task(Func<TaskList, IBuilder> builderStrategy)
{
_builderStrategy = builderStrategy;
}
public IBuilder GetBuilder(TaskList todoList))
{
return _builderStrategy(todolist);
}
}
public class Note : Task
{
public Note(Func<TaskList, IBuilder> builderStrategy) : base(builderStrategy) {}
}
// ...
note = new Note(x => return new noteBuilder(x));