I have a question that may be silly, but I'm new to C#, so pardon my insolence. I am wondering whether it is possible for a function to refer to an instance, which has been created by another function.
I am including an exemplary code to illustrate what I mean:
class Program
{
static void Main(string[] args)
{
Instantiator.Instantiate();
Referent.Refer(instance);
Console.ReadLine();
}
}
public class Instance
{
public void OnInstantiated()
{
Console.WriteLine("I have been instantiated.");
}
public void OnReferred()
{
Console.WriteLine("I have been referred to.");
}
}
public class Instantiator
{
public static void Instantiate()
{
Instance instance = new Instance();
instance.OnInstantiated();
}
}
public class Referent
{
public static void Refer(Instance instance)
{
if(instance != null)
{
instance.OnReferred();
}
else
{
Console.WriteLine("No instance to refer to.");
}
}
}
What could I use to be able to refer to the "instance" instance (which is created by the Instantiator.Instantiate function) in the Referent.Refer function?
Thanks in advance for your pertinent comments!
Make Instantiator return the class when done
public class Instantiator
{
public static Instance Instantiate()
{
Instance instance = new Instance();
instance.OnInstantiated();
return instance;
}
}
class Program
{
static void Main(string[] args)
{
var instance = Instantiator.Instantiate();
Referent.Refer(instance);
Console.ReadLine();
}
}
The pattern Instantiate() is doing is often called the "Factory Pattern"
Another option you could use is the Singleton pattern. If you also need your instance to be only one, you can give the responsibility to create a new instance and return it afterwards to the class itself.
class Program
{
static void Main(string[] args)
{
Instance.Instantiate();
Referent.Refer(Instance.GetInstance());
Console.ReadLine();
}
}
public class Instance
{
private static Instance myInstance;
public void OnInstantiated()
{
Console.WriteLine("I have been instantiated.");
}
public void OnReferred()
{
Console.WriteLine("I have been referred to.");
}
public static void Instantiate()
{
myInstance = new Instance();
myInstance.OnInstantiated();
}
public static Instance GetInstance()
{
return myInstance;
}
}
public class Referent
{
public static void Refer(Instance instance)
{
if (instance != null)
{
instance.OnReferred();
}
else
{
Console.WriteLine("No instance to refer to.");
}
}
}
Related
i feel stupid really, but i think i am being snow blind. i cannot access a singleton class method when calling from another classy. i get the dreaded
(NullReferenceException).
here are both my simple singleton and how i am calling the method.
public class PlayerNodePosition : MonoBehaviour
{
public static PlayerNodePosition instance;
string code;
void Awake()
{
if (instance == null)
{
Debug.LogWarning("More than one instance of Inventory found!");
return;
}
instance = this;
}
public void AddCode(string _code)
{
code = _code;
}
}
and here is the caller from another script.
void AddCode()
{
PlayerNodePosition.instance.AddCode("Added!");
}
being a "simpleton" i am obviously missing the obvious.
You don't instantiate instance anywhere. You would need something like
private static PlayerNodePosition playerNodePosition;
public static PlayerNodePosition instance
{
get
{
if (playerNodePosition == null) {
playerNodePosition = new PlayerNodePosition();
}
return playerNodePosition;
}
}
The method Awake should be static and the instance should be set. I have no chance to check whether this runs as I have no C# installed, but the Debug log warning you give is logically wrong. If there is no instance, you need to create one. If there is an instance, you return that one. This is the singleton pattern.
public class PlayerNodePosition : MonoBehaviour
{
public static PlayerNodePosition instance;
string code;
void static getInstance()
{
if (instance == null)
{
instance = new PlayerNodePosition();
}
return instance;
}
public void AddCode(string _code)
{
code = _code;
}
}
Hello I am new to programming.
Basically I need to store a method A from class A in variable A from class B inside a method from class B but I cannot seem to find a way.
To give an example:
Class A
public void methodA()
{
*method*
}
Class B
Delegate variableA; //I believe using Delegate is wrong
public void methodB();
{
variableA = ClassA.methodA();
}
Then in Class B there would be another method that will utilize the variable with the stored method.
public void methodC();
{
variableA;
}
This isn't the exact code I have but this is basically the gist of it. Any help is appreciated :)
Edit: Thanks for the help everyone!
ClassA definition:
public class ClassA
{
public void MethodA()
{
Console.WriteLine("Hello World!");
}
}
ClassB definition:
public class ClassB
{
private Action VariableA { get; set; }
public void MethodB(ClassA classA)
{
VariableA = classA.MethodA;
}
public void MethodC()
{
VariableA();
}
}
Program definition:
static void Main(string[] args)
{
ClassA classA = new ClassA();
ClassB classB = new ClassB();
classB.MethodB(classA);
classB.MethodC();
Console.ReadLine();
}
Here is an example:
public class Test
{
private Action<int> hiddenMethod = new Action<int>((i) =>
{
Console.WriteLine(i);
});
public void PublicMethod(int i)
{
hiddenMethod(i);
}
}
And using it:
class Program
{
static void Main(string[] args)
{
Test t = new Test();
t.PublicMethod(21);
Console.Read();
}
}
Use reflection:
public class A
{
public void MethodA()
{
Console.WriteLine("MethodA");
}
public static void StaticMethodA()
{
Console.WriteLine("StaticMethodA");
}
}
public class B
{
MethodInfo mv = typeof(A).GetMethod("MethodA");
MethodInfo smv = typeof(A).GetMethod("StaticMethodA");
public void CheckA(bool useStatic)
{
if (useStatic) smv.Invoke(null, null);
else mv.Invoke(new A(), null);
}
}
class MainClass
{
[STAThread]
public static void Main(string[] args)
{
var b = new B();
b.CheckA(true);
b.CheckA(false);
}
}
See details in MSDN.
I've inherited a large codebase and I'm trying to implement some new functionality into the framework. Basically, in order to do it the "right" way, I would have to modify the entire structure of the framework. since I'm not the guy who designed the framework, nor am I a mind reader, doing so probably isn't going to happen (although I would really love to redesign it all from scratch myself).
So in order to do what I want, I'm trying to implement a decorator pattern, of sorts. This answer from maliger suggests that what I'm doing below is perfectly valid. However, mono doesn't seem to like it; it complains that T cannot be derived from when I declare HappyDecorator
Please forgive the overly simplistic example, but it gets the point across.
public class HappyObject
{
public virtual void print()
{
Console.WriteLine ("I'm happy");
}
}
public class VeryHappyObject : HappyObject
{
public override void print()
{
Console.WriteLine ("I'm very happy");
}
public void LeapForJoy()
{
Console.WriteLine("Leaping For Joy!");
}
}
public class SuperHappyObject : VeryHappyObject
{
public override void print()
{
Console.WriteLine ("I'm super happy!");
}
public void DieOfLaughter()
{
Console.WriteLine("Me Dead!");
}
}
public class HappyDecorator<T> : T where T : HappyObject
{
public string SpecialFactor { get; set; }
public void printMe()
{
Console.WriteLine (SpecialFactor);
print();
}
}
class MainClass
{
public static void Main (string[] args)
{
HappyDecorator<HappyObject> obj = new HappyDecorator<HappyObject> ();
obj.SpecialFactor = Console.ReadLine();
obj.printMe();
}
}
You're typing HappyDecorator to T, but there's no instance of T to use inside that class.
public class HappyDecorator<T> where T : HappyObject
{
private readonly T _instance;
public HappyDecorator(T instance)
{
_instance = instance;
}
public string SpecialFactor { get; set; }
public void printMe()
{
Console.WriteLine(SpecialFactor);
_instance.print();
}
}
Another alternative is to structure it like this with a generic method instead of a generic class. It's not really a decorator then though:
public class HappyDecorator
{
public string SpecialFactor { get; set; }
public void printMe<T>(T instance) where T : HappyObject
{
Console.WriteLine(SpecialFactor);
instance.print();
}
}
And call like:
HappyDecorator obj = new HappyDecorator();
obj.SpecialFactor = Console.ReadLine();
obj.printMe(new HappyObject());
I think this is what you are trying to do:
public interface IhappyObject
{
void Print();
}
public class HappyObject : IhappyObject
{
private IhappyObject obj;
public HappyObject(IhappyObject obj)
{
this.obj = obj;
}
public void Print()
{
obj.Print();
}
}
public class VeryHappyObject : IhappyObject
{
public void Print()
{
Console.WriteLine("I'm very happy");
}
}
public class SuperHappyObject : IhappyObject
{
public void Print()
{
Console.WriteLine("I'm super happy!");
}
}
static void Main(string[] args)
{
HappyObject obj = new HappyObject(new SuperHappyObject());
obj.Print();
}
Assume I have a code:
class Module1 {
public static void Main(string[] args) {
Module1.level1();
}
public static void level1() {
Module1.level2();
}
public static void level2() {
Module2.level1();
}
}
[DetectWhenFlowExitsClass] // <-- note aspect
class Module2 {
public static void level1() {
Module2.level2();
}
public static void level2() {
Module2.level3();
}
public static void level3() {
throw new SystemException("oops");
}
}
After calling Main() I get a stacktrace:
Unhandled Exception: System.SystemException: oops
at Test.Module2.level3()
at Test.Module2.level2()
at Test.Module2.level1()
at Test.Module1.level2()
at Test.Module1.level1()
at Test.Module1.Main(String[] args)
Question
How to write aspect which detects moment when "control flow" exits code of class Module2?
That is, when Test.Module2.level1() finishes its work [here, due to exception].
Exist any shortcuts for this in PostSharp?
The most basic way would be to use OnMethodBoundaryAspect, which allows you to handle the method entry and method exit advices. You will need to count number of method of each particular class on the stack and when this count goes from 1 to 0, the control is leaving methods of the aspected class.
Here is the sample aspect code:
[Serializable]
public class DetectWhenFlowExitsClass : OnMethodBoundaryAspect
{
[ThreadStatic] private static Dictionary<Type, int> stackCounters;
private Type declaringType;
public override bool CompileTimeValidate(MethodBase method)
{
declaringType = method.DeclaringType;
return true;
}
private void EnsureStackCounters()
{
if (stackCounters == null)
stackCounters = new Dictionary<Type, int>();
}
public override void OnEntry(MethodExecutionArgs args)
{
EnsureStackCounters();
int counter;
stackCounters.TryGetValue(declaringType, out counter);
stackCounters[declaringType] = ++counter;
}
public override void OnExit(MethodExecutionArgs args)
{
EnsureStackCounters();
int counter;
stackCounters.TryGetValue(declaringType, out counter);
stackCounters[declaringType] = --counter;
if (counter == 0)
Console.WriteLine("Control leaving class {0}", declaringType.Name);
}
}
You will probably need to tinker with this aspect implementation a bit, but it works in basic situations.
With this code:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("saturnisko: {0}", UkladSloneczny.saturn.mass);
}
}
public class UkladSloneczny
{
private Saturn sat;
public UkladSloneczny(Saturn sat)
{
this.sat = sat;
}
public Saturn saturn
{
get { return this.sat; }
}
}
public class Saturn
{
private int masa;
public Saturn() { masa = 0; }
public int mass
{
get { return this.masa; }
}
}
Why I am getting error like so:
Error 1 An object reference is required for the non-static field, method, or property 'ConsoleApplication1.UkladSloneczny.saturn.get'
?
I assume you're getting it here: Console.WriteLine("saturnisko: {0}", UkladSloneczny.saturn.mass);
UkladSloneczny isn't a static class, so you can't call it like that. You need to either make it static or make a new instance of the class and then call yourClassInstance.saturn.mass.
If the class, method or property are not static then you have to instantiate the object in memory to be able to do anything with it, otherwise the object is null.
So either:
public static class UkladSloneczny
{
private static Saturn sat;
public UkladSloneczny(Saturn sat)
{
sat = sat;
}
public static Saturn saturn
{
get { return sat; }
}
}
OR
new UkladSloneczny().saturn.mass
You need to call it from an instance of UkladSloneczny, like this:
class Program
{
static void Main(string[] args)
{
Saturn saturn = new Saturn();
UkladSloneczny ukladSloneczny = new UkladSloneczny(saturn);
Console.WriteLine("saturnisko: {0}", ukladSloneczny.saturn.mass);
}
}
You need to make an object for UkladSloneczny:
class Program
{
static void Main(string[] args)
{
UkladSloneczny instance = new UkladSloneczny(new Saturn());
Console.WriteLine("saturnisko: {0}", instance.saturn.mass);
}
}
Or you can make the mass of saturn a static property:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("saturnisko: {0}", Saturn.mass);
}
}
public class Saturn
{
private static int masa = 0;
public Saturn() { }
public static int mass
{
get { return masa; }
}
}