I got something like the following:
class Factory{
private List<FactorizableObject> _collected; //Collection of all created objects
public FactorizableObject createObject (someParams DontMatter){
FactorizableObject newObject = new FactorizableObject(DontMatter);
_collected.Add(newObject);
return newObject;
}
public void DoSomethingWithCollectedObjects(){
//Work with created objects
}
}
class UsingClass1{
private FactorizableObject myObject;
public UsingClass1(){
myObject = Factory.createObject(someParams);
}
}
class UsingClass2{
private FactorizableObject myObject;
public UsingClass2(){
myObject = Factory.createObject(someOtherParams);
}
}
class WorkingClass{
List<UsingClass1> someOfThese;
List<UsingClass2> someOfThose;
private void triggerWork(){
someOfThese.Remove(RemoveSomeObject);
Factory.DoSomethingWithCollectedObjects();
}
}
Now my Problem is: Even if I remove an instance of a usingClass from on of these lists, the entries in the factory still keep alive and get used when calling DoSomethingWithCollectedObjects. I expected something like a NullreferenceException when trying to work on the object.
The Question: Is there a way to kill the object (the reference to the object) without explicit removing it from the factory-collection? This would need to be done in any class using the factory, so I would like to get around this...
I need some collection like this to perform some special actions on the factorized objects and dont want to care where they are located (The action needs to be done on ALL of the objects). I already tried setting UsingClass1.myObject = null, before removing the object, but this only removed my reference onto the factorized object.
Related
What I am trying to do is find the most elegant way to create a "pointer-like" class for a specific object/class type that I have in a project.
What I mean is a little confusing without an example. Take this really simple class:
public class MyClass
{
private string _name;
public string GetName() { return _name; }
public void SetName(string name) { _name = name; }
}
I want to create a second class which is like a pointer to it like this:
public class MyClassPtr
{
private MyClass _obj;
public bool IsValid = false;
public MyClassPtr(MyClass obj) { _obj = obj; IsValid = true; }
public void InvalidatePtr()
{
IsValid = false;
obj = null;
}
// SOME MAGIC HERE?
}
The challenge: The key is that I want to elegantly have MyClassPtr provide an interface to all of the public methods/members in MyClass without writing wrappers and/or accessors around each method/member.
I know that I could do this:
public class MyClassPtr
{
public string GetName() { return _obj.GetName(); }
...
}
But that's what I want to avoid. Is there some fundamental abstraction that I don't know of that I can apply to MyClassPtr to allow it to easily re-expose the methods/members in MyClass directed through _obj? I do NOT want MyClassPtr to inherit MyClass. Should MyClassPtr be a type instead, and some trick with accessors to expose the methods/members of MyClass?
Edit: More context on why I am looking for such a design through an example. Here is the overall goal. Imagine a platform that parses through data about people and when it finds information about a person, it creates an instance of Person with that information. You could get a handle to that person like:
Person person1 = platform.GetPerson(based_on_data);
Now, imagine the platform had two instances of Person that it thought were different people, but all of a sudden information came in that strongly suggested those two instances actually refer to the same person. So, the platform wants to merge the instances together in to a new object, let's call it personX.
Now, floating around in the platform someone had a copy of one of those two instances that got merged, which was person1. What I want to do is on-the-fly replace person1 with personX. Literally, I want person1==personX to be true, NOT just that they are two different objects with the same data. This is important since the platform could make a change to personX and unless the two objects are literally equal, a change to personX would not be automatically reflected in person1.
Since I can't on-the-fly replace person1 with personX I had that idea that I wouldn't give direct access to Person, instead I would give access to PersonPtr which the platform (on-the-fly) can change what Person it is pointing to. This would insurance that once person1ptr gets updated to point to personX, if a change is made in personX it will be seen in person1ptr
You could of course use something like
public class MyClassWrapper
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public void Invoke(Action<MyClass> action)
{
action(_obj);
}
public U Invoke<U>(Func<MyClass, U> func)
{
return func(_obj);
}
public void ChangeTo(MyClass obj)
{
_obj = obj;
}
}
Given your class looks like
public class MyClass
{
public string Name { get; set; }
}
Example:
var person1 = new MyClass { Name = "Instance1" };
var person2 = new MyClass { Name = "Instance2" };
var wrapper = new MyClassWrapper(person1);
wrapper.Invoke(x => x.Name += "original");
var x = wrapper.Invoke(x => x.Name); // Instance1original
wrapper.ChangeTo(person2);
var y = wrapper.Invoke(x => x.Name); // Instance2
but it has a major drawback: you can't access members directly, so you can't bind the data (to a DataTable or a Control).
It would be better to implement all members of your class also in your wrapper class. If you're afraid changes in your class will be forgotten to be implemented in your wrapper, just use an interface:
public interface IMyClass
{
string Name { get; set; }
}
public class MyClass : IMyClass
{
public string Name { get; set; }
}
public class MyClassWrapper: IMyClass
{
MyClass _obj;
public MyClassWrapper(MyClass obj)
{
_obj = obj;
}
public string Name
{
get { return _obj.Name; }
set { _obj.Name = value; }
}
}
Note that regardless which approach you use, you'll have to always keep a reference to the wrapper instance to actually change the underlying instance (using something like static aside).
Also, changing the underlying instance of such a wrapper without telling the component using it that it changed don't seem to be a good idea. Maybe your system is simple enough to get away with a wrapper; that's something you have to decide for yourself.
Maybe your wrapper should simply have an Invalid flag (and/or use an event to signal a change of the underlying object.). Once the underlying object is merged, it is set to true and each member access should throw an exception. This would force the component using the wrapper to deliberately react to changes and to reload the data from your service.
All in all, I think using such a wrapper will just clutter up your code and be error prone (just imagine adding multithreading to the mix). Think twice if you really need this wrapper.
Why not just simply ask your service for a new instance of your class everytime you use it (the service can simply use a cache)? Sure, you can't prevent that someone somewhere keeps a reference; but at least you'll keep your sanity.
Context: this is based on a question that was asked and then deleted before I could answer it - but I think it is a good question, so I've tidied it, rephrased it, and re-posted it.
In a high-throughput scenario using protobuf-net, where lots of allocations are a problem (in particular for GC), is it possible to re-use objects? For example by adding a Clear() method?
[ProtoContract]
public class MyDTO
{
[ProtoMember(1)]
public int Foo { get; set; }
[ProtoMember(2)]
public string Bar { get; set; }
[ProtoMember(3, DataFormat = DataFormat.Group)]
public List<int> Values { get { return values; } }
private readonly List<int> values = new List<int>();
public void Clear()
{
values.Clear();
Foo = 0;
Bar = null;
}
}
protobuf-net will never call your Clear() method itself, but for simple cases you can simply do this yourself, and use the Merge method (on the v1 API, or just pass the object into Deserialize in the v2 API). For example:
MyDTO obj = new MyDTO();
for(...) {
obj.Clear();
Serializer.Merge(obj, source);
}
This loads the data into the existing obj rather than creating a new object each time.
In more complex scenarios where you want to reduce the number of object allocations, and are happy to handle the object pooling / re-use yourself, then you can use a custom factory. For example, you can add a method to MyDTO such as:
// this can also accept serialization-context parameters if
// you want to pass your pool in, etc
public static MyDTO Create()
{
// try to get from the pool; only allocate new obj if necessary
return SomePool.GetMyDTO() ?? new MyDTO();
}
and, at app-startup, configure protobuf-net to know about it:
RuntimeTypeModel.Default[typeof(MyDTO)].SetFactory("Create");
(SetFactory can also accept a MethodInfo - useful if the factory method is not declared inside the type in question)
With this, what should happen is the factory method is used instead of the usual construction mechanisms. It remains, however, entirely your job to cleanse (Clear()) the objects when you are finished with them, and to return them to your pool. What is particularly nice about the factory approach is that it will work for new sub-items in lists, etc, which you can't do just from Merge.
I have a class A which holds a collection of objects. Every instance of the class fills the collection according a different logic. From time to time I need to update all the collections.
I was thinking this could be done maybe if the class has a method that holds the logic for filling the collection and I can set this logic at the time of the creation of the object.
Like this:
MyClass instance = new MyClass();
instance.updateCollection = { logic for filling the collection } //
The logic will be different for each object.
Thanks
You can achieve this easily with an Action.
Either pass yor desired Action in the constructor, or make a property that allows you to set the desired Action.
Sounds like you should be using something like a Factory which creates these objects, but stores a reference to them as well. You can then have a separate method inside your factory to update each collection inside the factory.
Also - don't constrain yourself to one class. If you embrace the ideas of polymorphism and inheritance instead of fighting them, you'll find C# a lot easier and more fun.
Here is an example using Action class:
class MyClass
{
private readonly Action<List<string>> _updateAction;
private readonly List<string> _collection = new List<string>();
public MyClass(Action<List<string>> updateAction)
{
_updateAction = updateAction;
}
public void Update()
{
_updateAction(_collection);
}
}
class MyClassTester
{
public static void Test()
{
MyClass weekdayAdder = new MyClass(c => c.Add(DateTime.Now.DayOfWeek.ToString()));
MyClass timeAdder = new MyClass((c) => c.Add(DateTime.Now.ToShortTimeString()));
weekdayAdder.Update();
weekdayAdder.Update();
timeAdder.Update();
timeAdder.Update();
timeAdder.Update();
}
}
In the below code, I would like to use the code in static load method to refresh the object... but how would I reset the current object with new object ? Is copying field by field is the only way ?
class WIP
{
// <Snipped> Various other properties...
public Boolean Refresh()
{
// Need to change the current object with the updated object
this = WIP.Load(this.ObjectID); // Says this is readonly...
return true;
}
public static WIP Load(long ObjectID)
{
// This static method fetches the data from DB and returns the object.
}
}
Edit : I just got this idea after posting the question... Are there any traps in this ?
class WIP
{
// <Snipped> Various other properties...
public Boolean Refresh()
{
// This method fetches the data from DB and updates the object.
}
public static WIP Load(long ObjectID)
{
WIP newObject = new WIP();
newObject.ObjectID = ObjectID;
newObject.Refresh();
return newObject;
}
}
No, you can't. The closest you can come is basically to copy every member - which isn't going to work if some are read-only, of course.
Either you're trying to make your object immutable - in which case it shouldn't change under the feet of code which already has a reference to your object - or you're not, in which case you just need to make it fully mutable (ideally in some atomic fashion if there are multiple threads involved).
Sounds like you need "WIP factory":
class WIP
{
private static Dictionary<long, WIP> instances = new Dictionary<long, WIP>();
private WIP()
{
...
}
// <Snipped> Various other properties...
public Boolean Refresh()
{
// This method fetches the data from DB and updates the object.
}
public static WIP Load(long ObjectID)
{
WIP wip = null;
if (instances.ContainsKey(ObjectID))
{
wip = instances[ObjectID];
}
else
{
wip = new WIP();
wip.ObjectID = ObjectID;
instances.Add(ObjectID, wip);
}
wip.Refresh();
return wip;
}
}
This will cause that the only way to get instance of WIP is through the static "Load" method, and you will be using the same instance for every ObjectID unlike your current code that let anyone create new instance for the same ID.
This way calling the Refresh will update all the instances, no matter where they are.
You can't.
Just think that every other object that holds a reference to the object that you're trying to "refresh" should be updated. You're only chance is to add an indirection level or to change your software's design.
The Static method indicates that it is kind of a "Factory-Style" implementation. Hence should be used to create or get new instances of objects.
The Refresh method on the other side would naturaly be used to just refresh the properties on the current object and leaving the objects reference intact.
Usage:
// Initialize the object
WIP myWip = WIP.Load(1);
Console.WriteLine(myWip.ObjectId);
// Refresh the object from underlying data store
myWip.Refresh();
// <Snipped> Various other properties...
public Boolean Refresh()
{
//Read the values from data store and refresh the properties...
return true;
}
public static WIP Load(long ObjectID)
{
// This static method fetches the data from DB and returns the object.
}
For the Lifecycle-Management of objects I'd use some Factories. You might take a look at the factory pattern -> http://en.wikipedia.org/wiki/Factory_method_pattern.
You can't use this keyword in a static method. Hence you can't use instance variables either.
I want to have multiple objects share a reference through a private field, such that any of the objects can assign to the field, and the updated field will be seen by other objects sharing that reference. What I was originally hoping to do was this:
class SomeObject
{
private ref DataObject _data;
public SomeObject(ref DataObject data)
{
_data = ref data; // or something similar
}
public ChangeData(DataObject newData)
{
_data = data;
// at this point, *other* SomeObject instances that were
// created with the same reference should also have _data == newData
}
}
But of course you can't use ref that way: ref is only for method parameters. And a static field won't work, since not all SomeObject instances should refer to the same object---rather, the object in question should be set in the constructor.
Obviously I could solve this by just adding a simple wrapper class. But is there a better way? Is there some kind of SharedReference<T> class that I can use?
Update, since most of the answers misunderstood what I was asking. I know that the _data field contains a reference to the original DataObject. What I want is another level of indirection. I want to be able to change which object I'm pointing to in one instance, and have the new value be picked up by other instances that were created with the same reference. As the updated code sample shows, I want to assign to _data, and effectively change the value of _data in other instances.
I don't know of any class that you can use for this, but I seems quite easy to implement your own SharedReference<T> class.
Something like this:
public sealed class SharedReference<T>
where T : class
{
public T Reference
{
get; set;
}
}
You could simply use an array of shared objects, and reassign the array elements:
class SomeObject
{
// you probably want to make this readonly
private readonly DataObject[] _data;
public SomeObject(DataObject[] data)
{
_data = data;
}
public void ChangeData(DataObject newData)
{
_data[0] = o;
}
// and you could define your own accessor property...
private DataObject Data
{
get { return _data[0]; }
set { _data[0] = value; }
}
}
Apart from that, I think you'll need to define your own 'holder' class & use that
If you simply provide a reference to the object without the ref keyword, you will get the behaviour you want. Using ref is actually passing a reference to a reference (pointer to a pointer), so unless you want to null someone else's reference, it won't be of any use to you.
Update: Sorry I didn't spot that you wanted to re-assign a completely new object into the field and have that reflected throughout. You are best actually creating either a wrapper class to contain the object state and modify that, or a common event that all instances can subscribe to such that when you want to change the object, fire the event with the new object inside it and have each instance update it's own internal reference.
Alternatively, use the Singleton pattern - everyone accesses a publicly available static reference, but unlike the traditional Singleton, you let them change the reference if they want to - so everyone can see the change. This also has the benefit that the objects don't need internal references.
Alternatively again, have the data class expose a method allowing it to consume another data class and copy its state across - like cloning.
In C#,
class SomeObject
{
private DataObject _data;
public SomeObject(DataObject data)
{
_data = data;
}
}
in fact does exactly what you want, if DataObject is a Reference Type, which is true for all classes.
Please disregard this answer since I misunderstood the initial question.Other answers here cover the topic fully.