RunUO Community

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Little Tutorial

MarciXs

Sorceror
So the other day I suggested having set DataPath.CustomPath static string field to public. So that, instead of modifying the actual script file I could create a Config class that would look something like this:
public class ConifguraXtion
{
public static void Configure()
{
// * for reference
DataPath.CustomPath = "...";
}
}
needless to say as with any suggestion(most) it ended up in different sort of discussion.
Anyway
since, it's private that would result(example) in an compiler error.

So thus the tutorial, albeit a simple one.
What exactly is it for? So that you don't have to modify any of SVN distro files.
Here goes, using this very simple static method, what it does it accesses this private field and sets its value. Or changes in this case.
public class Extender
{
public static void ChangeStatic(Type t, string name, object value, object instance)
{
FieldInfo f = t.GetField(name, BindingFlags.NonPublic | BindingFlags.Static);
if (f != null)
f.SetValue(instance, value);
}
}

As you can see it's very basic, but will do what I(we?) need.

so let's return back to *
now the line would look as follows:
string fx = "location of files";
Extender.ChangeStatic(typeof(DataPath),"CustomPath",fx,null); // we pass null as the last argument cause it's an static field.

So now all we have to do is make sure our class gets called before DataPath can get its dirty hands on it. I've read where some people say that we can't be sure of the order we get our class initialized/configured. While this is true it's not true we can't control the flow(for our classes anyway).
Which we can see here from ScriptCompiler
invoke.Sort( new CallPriorityComparer() );
So how does it work?
Well, quite simple, you simply decorate your method with the CallPriorityAttribute.
[CallPriorityAttribute(Int32.MaxValue)]
public static void Configure()
{
}
As long as you don't specify the same numbers you can always control the flow. Also, the lower the number the higher the priority. Thus the method gets called first.
For instance,method decorated as priority of 1 would get called before 100;

Before I wrap it all up, one more thing. While on subject about reflection and that alike, I've noticed when someone is copying an object usually the public properties are being saved/written. However you can do this also for the private fields , achieving a very deep copy.
I mean for instance, you had
public class Turtle
{
private int _shyPoints;
private int _Points;
public int Points { get { return _shyPoints; } set { _shyPoints = value; }}
}
Normally, shy points wouldn't get copied.
However,
a little example:

public class A
{
public A Base;
private int _H;

public void Save()
{

if (Base == null)
Base = new A();
BindingFlags privates = BindingFlags.NonPublic | BindingFlags.Instance;
foreach (FieldInfo fields in this.GetType().GetFields(privates))
{
FieldInfo f = this.Base.GetType().GetField(fields.Name,privates);
if(f!=null)
f.SetValue(this.Base, fields.GetValue(this));
}
}

}
Shows a very basic way for a deep copy. Deep copies aren't always necessary though. Was in my case, figured to share few tips.
I don't know if it helps anyone or not.

Anyway.

P.S Actually after I've written all this I looked at the DataPath script and realized that I could also simply have a class that is called before DataPath ( using the call priority )
and does the following:
Core.DataDirectories.Add("your file");
Would work as well :-/. Go figure.
 
Top