Reset this with new object - c#

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.

Related

C# Make a class return its instance without a function or variable

So I've been working with classes with single instances in Unity for a while and generally do this:
class PublicThings {
public static PublicThings I; // instance of this class
public int Score;
void Start { I = GetComponent<PublicThings>(); }
}
Usage: PublicThings.I.Score = 10;
Which works pretty well. However, I've been curious as to whether or not it's possible to have the instance of the class be returned without having to type .I after the class.
So basically here's how it would look instead:
PublicThings.Score = 10;
This question seems like it's relevent but I'm having trouble getting it to work.
Is this possible? If so, how would it be done?
Three options to do what you are looking to do:
Make a static property/field with the static keyword in the PublicThings class
Make a ScriptableObject and attach it to the item that is calling it (video tutorial)
Utilize the Singleton Pattern (I would suggest avoid using this method before trying the other two)
Also it's worth noting that the Singleton Pattern doesn't necessarily solve your problem. You will still have to call something like PublicThings.instance.Score.
Hope this helps.
Singleton pattern is the way to go.
Also, with lazy instantiation.
public class PublicThings
{
private static PublicThings _instance;
// Your private constructor
private PublicThings() { }
public static PublicThings Instance
{
get
{
if (_instance == null)
{
// Construction of instance logic here
_instance = new PublicThings();
}
return _instance;
}
// No setter, read-only property
}
// Decide if Score is a read-only property or not.
public int Score { get; set; }
}
Whener the single instance of PublicThings is required, it will be constructed and then stored. A second access to the instance will provide the stored one.
[Test]
public void WithTwoAccess_ToSingleInstance_MustBeTheSame()
{
var things1 = PublicThings.Instance;
var things2 = PublicThings.Instance;
Assert.AreSame(things2, things1);
// Asserts true
}
If your Score property must be set once, just change que Instance property to a method (commonly called GetInstance) which expects the value of Score.
Hope it helps.

Is there a way for a getter in C# to cache its result in-line?

I've been working on a Discord bot and one of my abstract classes that represents servers ("Bot Contexts") contains the following data.
public virtual Command[] ContextSpecificCommands { get; } = null;
In user-defined Contexts I expect them to override this (if the server that has this code needs to). There's an issue, however, which is that I expect Commands to be singletons in the scope of a Context. This means that CommandFoo can exist only once in CoolContextNumberOne, and can also exist in CoolContextNumberTwo (as a separate instance of CommandFoo), but a single context cannot have two instances of CommandFoo in it.
My issue comes in with the behavior of getters. If the user does this...
public override Command[] ContextSpecificCommands => new Command[] {
new CommandFoo()
};
Then this will instantiate CommandFoo every time ContextSpecificCommands is referenced.
Is there any way to ensure that ContextSpecificCommands is cached in-line so that it only instantiates that container array once? I'd like to avoid requiring the user to specify a field and point to that field if possible.
This code was for the intellectual exercise, it is not recommended!
If you are willing to force the implementors of your BotContexts to use a specific form, then you can insert a type of singleton pattern into the property definition.
Consider:
public static class Singleton {
public static T For<T>(Func<T> makeSingleton) => Singleton<T>.For(makeSingleton);
}
public static class Singleton<T> {
static Dictionary<Func<T>, T> Cache = new Dictionary<Func<T>, T>();
public static T For(Func<T> makeSingleton) {
T singleton;
if (!Cache.TryGetValue(makeSingleton, out singleton)) {
singleton = makeSingleton();
Cache[makeSingleton] = singleton;
}
return singleton;
}
}
Now you can use this like so:
public class CoolContextNumberOne : BotContexts {
public override Command[] ContextSpecificCommands => Singleton.For(() => new Command[] { new CommandFoo() });
}
public class CoolContextNumberTwo : BotContexts {
public override Command[] ContextSpecificCommands => Singleton.For(() => new Command[] { new CommandFoo() });
}
Each CoolContext will create one instance of CommandFoo regardless of how many times ContextSpecificCommands is called.
Since in C# the use of a new expression will always generate a new object, it is difficult (impossible?) to see how you could have the code the same and figure out when to generate a new object and when to return an existing object (e.g. if a Command was actually a proxy object). If you didn't mind a dependency on optimization being enabled, StackFrame and GetILOffset could help, but would probably fail in debug mode. And be very brittle.
It may be possible to hide the use of Singleton in the types of Commands by using dynamic and Expando but that seems like an even worse idea.
This is not natively possible without adding extra code.
In order for a result to cache, a separate backing field must be created and the code must be set up to work with this field.
In order to resolve my dilemma, I have altered my code from:
// User will override this.
public virtual Command[] ContextSpecificCommands { get; } = null;
To:
// User will override this.
protected virtual Command[] ContextSpecificCommands { get; } = null;
// These control the cache.
private bool HasPopulatedCommandCache = false;
private Command[] CommandCache = null;
// Things will reference this to get ahold of commands.
public Command[] Commands {
get {
if (!HasPopulatedCommandCache) {
HasPopulatedCommandCache = true;
CommandCache = ContextSpecificCommands;
}
return CommandCache;
}
}
This allows the code to meet all of the goals specified in my original question. The user's class can use an in-line expression to define their commands without the worry of this array being instantiated every time it is referenced.

Remove second reference to object

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.

Replace object instance with another in C#

In this question I would like to find out if and how this is possible. This technique would seem extremely bad practice but it seems that the API (UnityEditor) that I am using, is doing something like this and I am just curious.
If there are multiple references to the same object, is it possible to instantiate a new object into the same memory slot so that all previous references point to the new object?
I figured out that the only feasible way to do so is by using unmanaged C++. Essentially the following is happening:
// Original prefab
GameObject prefab = x;
prefab.tag = "Untagged";
// A copy of the original prefab
GameObject prefabCopy = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
prefabCopy.tag = "EditorOnly"; // Change from initial value "Untagged"
Debug.Log(prefab.tag); // "Untagged" - expected
Debug.Log(prefabCopy.tag); // "EditorOnly" - expected
// Replace contents of prefab file with `prefabCopy`
PrefabUtility.ReplacePrefab(prefabCopy, prefab);
// Destroy the copy
DestroyImmediate(prefabCopy);
Debug.Log(prefab.tag); // "EditorOnly" - whoa?
Some how prefab is now pointing to a different object?
Note: Bear in mind that Unity is built on top of the Mono flavour of .NET
Since an object state is defined by field values, you can copy memory, containing field values, from one object to another, effectively "replacing" it:
public static void Replace<T>(T x, T y)
where T : class
{
// replaces 'x' with 'y'
if(x == null) throw new ArgumentNullException("x");
if(y == null) throw new ArgumentNullException("y");
var size = Marshal.SizeOf(typeof(T));
var ptr = Marshal.AllocHGlobal(size);
Marshal.StructureToPtr(y, ptr, false);
Marshal.PtrToStructure(ptr, x);
Marshal.FreeHGlobal(ptr);
}
Note that this code requires [StructLayout(LayoutKind.Sequential)] (or LayoutKind.Explicit) attribute defined for a class.
You could do that if you embed your object into another one that is used to access the object.
class ObjectReference<T>
where T : new()
{
private T _obj = new T();
public void CreateNewObject()
{
_obj = new T();
}
public T Value { get return _obj; }
}
Now you can create multiple references to an object of type ObjectReference and only change the local object. The "real" object would be accessed through the Value property
A slightly different approach is that you create a wrapper that implements the same interface as your "real" object, thus making this wrapping transparent.
interface ISomeInterface
{
string PropertyA { get; set }
void MethodB (int x);
}
class TheRealObject : ISomeInterface
{
public string PropertyA { get; set }
public void MethodB (int x)
{
Console.WriteLine(x);
}
}
class Wrapper : ISomeInterface
{
TheRealObject _obj = new TheRealObject();
public string PropertyA
{
get { return _obj.PropertyA; }
set { _obj.PropertyA = value; }
}
public void MethodB (int x)
{
_obj.MethodB(x);
}
public void CreateNewObject()
{
_obj = new TheRealObject();
}
}
Now the wrapper can be used as if it was the "real" object. You could also pass an initial instance of the "real" object in the wrapper's constructor and remove the initializer of _obj.
No, that's not possible.
To actually change all references to an object, you would have to freeze all threads in the process, and access their register sets and stack. That's what the garbage collector does, but it's not possible for regular code.
What the method most likely does is to make a deep copy of one object onto the other.
If it is a custom Class you want to reference, i think you can have all the references point to a Fake Reference...
create your class (A)
create your class Interface (IA)
Create a wrapper class based on your interface which just passes all calls to a contained object (AC)
I Added a Assignment operator so i have all A Objects as ACs.
class AC:IA
{
IA ref;
AC(IA ref)
{
this.ref = ref;
}
public void ChangeReference(IA newRef) { ref = newRef;}
public static operator = (IA assignedObj)
{
return (assignedObject is AC) ? assignedObject : new AC(assignedObj);
}
// implementation of all methods in A
public override string ToString() { return ref.ToString(); }
...
}
Now if you want, you can use the ChangeReference method to switch all to the new Reference..
in C++ you would use Reference to Reference
Best of luck

Following the DRY principle in ASP.NET

I have just recently got involved in a classic ASP.NET project which contains lots of storing and reading values from the session and query strings. This could look something like the following:
Session["someKey"]=someValue;
And somewhere else in the code the value in the session is read. Clearly this violates the DRY principle since you'll have the literal string key spread out all over the code. One way to avoid this could be to store all keys as constants that could be referenced everywhere there is a need to read and write to the session. But I'm not sure that's the best way to do it. How would you recommend I best handle this so that I don't violate the DRY principle?
Create a separate public class where you can define your constants, e.g
public class SessionVars
{
public const string SOME_KEY = "someKey";
public const string SOME_OTHER_KEY = "someOtherKey";
}
and then anywhere in your code you can access session variables like this:
Session[SessionVars.SOME_KEY]=someValue;
This way you can get IntelliSence and other bells and whistles.
I think you're reading too much into DRY. I pertains more to things that could be wrapped up in a function. I.e. instead of repeating the same fives lines all over the place wrap those 5 lines in a function and call the function everywhere you need it.
What you have as an example is just setting a value in a dictionary (the session object in this case), and that is the simplest way to store and retrieve objects in it.
I can't remember for the life of me where I humbly re-purposed this code from, but it's pretty nice:
using System;
using System.Web;
namespace Project.Web.UI.Domain
{
public abstract class SessionBase<T> where T : class, new()
{
private static readonly Object _padlock = new Object();
private static string Key
{
get { return typeof(SessionBase<T>).FullName; }
}
public static T Current
{
get
{
var instance = HttpContext.Current.Session[Key] as T;
lock (SessionBase<T>._padlock)
{
if (instance == null)
{
HttpContext.Current.Session[Key]
= instance
= new T();
}
}
return instance;
}
}
public static void Clear()
{
var instance = HttpContext.Current.Session[Key] as T;
if (instance != null)
{
lock (SessionBase<T>._padlock)
{
HttpContext.Current.Session[Key] = null;
}
}
}
}
}
The idea behind it two fold. The type created should be the only type you need. It's basically a big strongly-typed wrapper. So you have some object you want to keep extending information in:
public class MyClass
{
public MyClass()
public string Blah1 { get; set; }
}
Then down the road you extend MyClass and you don't want to have to remember all the Key Values, store them in AppSettings or Const variables in Static Classes. You simply define what you want to store:
public class MyClassSession : SessionBase<MyClass>
{
}
And anywhere in your program you simply use the class.
// Any Asp.Net method (webforms or mvc)
public void SetValueMethod()
{
MyClassSesssion.Current.Blah1 = "asdf";
}
public string GetValueMethod()
{
return MyClassSession.Current.Blah1;
}
Optionally you could place the access to this session object in a base page and wrap it in a property:
class BasePage : Page
{
...
public string MySessionObject
{
get
{
if(Session["myKey"] == null)
return string.Empty;
return Session["myKey"].ToString();
}
set
{
Session["myKey"] = value;
}
}
...
}
Here you are repeating the myKey string but it is encapsulated into the property. If you want to go to the extreme of avoiding this, create a constant with the key and replace the string.

Categories

Resources