Sometimes you'd temporarily want to change the value of a variable, and the most common pattern is probably the one below;
string temp = someObject.SomeValue;
someObject.SomeValue = "Updating, call again later";
try
{
}
finally
{
someObject.SomeValue = temp;
}
I'm currently working in VB.NET, and it would seem like a dandy idea to be able to do something like the pattern below;
Imports System
Imports SubSystem
Public Class SomeLogger
Public CategoryName As String = "None Specified"
Public Sub DoLog(ByVal SomeText As String)
Console.WriteLine("{0}: {1}", CategoryName, SomeText)
End Sub
End Class
Public Class Application
Public Shared Logger As New SomeLogger
Public Shared Sub Main()
Logger.DoLog("Hello World")
Using Temporary.Override(Logger, "CategoryName", "Sub Main")
Logger.DoLog("Hello World")
End Using
Logger.DoLog("Hello World")
End Sub
End Class
Well, that's possible. Temporary is a static class, returning an IDisposable that wraps the property on said object. When the computer leaves the Using statement, the IDisposable will reflect the original value back, even if we exit the procedure by throwing a new exception.
The actual implementation as a reference;
using System;
using System.Collections;
using System.Reflection;
using System.IO;
using System.ComponentModel;
namespace SubSystem
{
public class Temporary
{
public static IDisposable Override (Object aObject, String aMemberName, Object aScopedValue)
{
return init (aMemberName, aObject.GetType (), aObject, aScopedValue);
}
public static IDisposable Override (Type aType, String aMemberName, Object aScopedValue)
{
return init (aMemberName, aType, null, aScopedValue);
}
static IDisposable init (String aMemberName, Type aType, Object aObject, Object aScopedValue)
{
MemberInfo memberInfo = aType.GetMember (aMemberName)[0];
switch (memberInfo.MemberType)
{
case MemberTypes.Property:
return new TemporaryOverrideProperty (
aObject == null ? aType : aObject,
(PropertyInfo)memberInfo,
aScopedValue);
case MemberTypes.Field:
return new TemporaryOverrideField (
aObject == null ? aType : aObject,
(FieldInfo)memberInfo,
aScopedValue);
default:
throw new NotSupportedException ();
}
}
}
public class TemporaryOverrideProperty : TemporaryOverride
{
PropertyInfo _overridenProperty;
public TemporaryOverrideProperty(Object aObject, PropertyInfo aProperty, Object aScopedValue)
{
this._sourceObject = aObject;
this.init(aProperty, aScopedValue);
}
public TemporaryOverrideProperty(Type aSource, PropertyInfo aProperty, Object aScopedValue)
{
this._sourceClass = aSource;
this.init(aProperty, aScopedValue);
}
~TemporaryOverrideProperty()
{
this.Dispose(false);
}
void init(PropertyInfo aProperty, Object aScopedValue)
{
this._overridenProperty = aProperty;
this._originalValue = this._overridenProperty.GetValue(this._sourceObject, null);
this._overridenProperty.SetValue(this._sourceObject, aScopedValue, null);
}
protected override void Dispose(Boolean disposing)
{
if (disposing)
{
this._overridenProperty.SetValue(this._sourceObject, this._originalValue, null);
}
base.Dispose(disposing);
}
}
public class TemporaryOverrideField : TemporaryOverride
{
FieldInfo _overridenField;
public TemporaryOverrideField(Object aObject, FieldInfo aField, Object aScopedValue)
{
this._sourceObject = aObject;
this.init(aField, aScopedValue);
}
public TemporaryOverrideField(Type aSource, FieldInfo aField, Object aScopedValue)
{
this._sourceClass = aSource;
this.init(aField, aScopedValue);
}
~TemporaryOverrideField()
{
this.Dispose(false);
}
void init(FieldInfo aField, Object aScopedValue)
{
this._overridenField = aField;
this._originalValue = this._overridenField.GetValue(this._sourceObject);
this._overridenField.SetValue(this._sourceObject, aScopedValue);
}
protected override void Dispose(Boolean disposing)
{
if (disposing)
{
this._overridenField.SetValue(this._sourceObject, this._originalValue);
}
base.Dispose(disposing);
}
}
public class TemporaryOverride : IDisposable
{
protected Object _sourceObject;
protected Type _sourceClass;
protected Object _originalValue;
protected TemporaryOverride()
{
}
#region IDisposable implementation (MSDN adapted version)
Boolean disposed = false;
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(Boolean disposing)
{
if (!this.disposed)
{
if (disposing)
{
}
this.disposed = true;
}
}
#endregion
}
}
I are Troll
|