How can I derive from a class through reflection? The following works for getting an existing instance and for creating a new instance of the class.
public class TreeViewSHWinstances {
[MenuItem("Reflect/CreateSHWinstances")]
static void Activate() {
Main();
}
static void Main() {
Assembly asm = typeof(UnityEditor.EditorWindow).Assembly;
Type wndType = asm.GetType ("UnityEditor.SceneHierarchyWindow");
// Grabs an existing instance if it exists and then sets the focus to it.
EditorWindow exstWnd = EditorWindow.GetWindow (wndType);
// Always create a new instance regardless if one already exists.
EditorWindow newWnd = (EditorWindow)Activator.CreateInstance (wndType);
}
}
This is what I actually want to do, but obviously the assembly is not yet loaded and when I have tried to acquire it form the above class I get an error that says it is not a Type even though I'm requesting wndType.
// THIS IS NOT INTENDED TO NOR DOES IT WORK.
public MySceneHierarchyWindow : UnityEditor.SceneHierarchyWindow {
}
My guess was to use Emit in some way, but I after experimenting with it I'm not sure it is the right direction.
Related
I’m trying to implement a simple singleton parent class for internal use (I only want to avoid static fields and don’t care about safety).
The reason I want a generic parent class is so I don’t have to worry about boilerplate and can simply inherit from Simpleton. I plan on having quite a few of these.
Here’s what I have:
class Simpleton
{
static Simpleton instance;
static Simpleton()
{
instance = new Simpleton();
}
// I know this naming isn’t ideal, but I’m going for brevity and I’m the only one using this codebase
static Simpleton I { get => instance; }
}
This works if I actually want to use an instance of Simpleton but I want to create a child class and use it:
class Settings : Simpleton
{
public int testSetting = 1;
}
// somewhere else
void Test()
{
// compiler error since Simpleton does not contain the field `testSetting`
var num = Settings.I.testSetting;
}
I just want to make the static Simpleton() function set instance to an instance of the child class. I can do this with reflection, but I can’t figure out how to do it such that the compiler knows that it is an instance of the child class.
I’m surprisingly stumped on how to make this work, and since my main goal is to have as little boilerplate as possible in the child class, I want to avoid overriding to whatever extent possible.
Make your Singleton a generic, and then derive Settings from Singleton<Settings>, like this:
var t = Settings.Instance.testSetting;
Console.WriteLine(t);
class Singleton<T> where T: new()
{
public static T Instance = new T();
}
class Settings : Singleton<Settings>
{
public int testSetting = 1;
}
I have 2 class projects. mqtt and Vm. so Vm class already referencing mqtt class and it works fine. now I want to creates a object of VM class in mqtt class project, which I understand create a circular dependency if I refer to the Vm class.
so I understand from google that I have to use interface, so I did and below is my code as follows.
mqtt class:
public class MqttControllerClass
{
InterfaceClass Mcallback = new MqttControllerClass(); //error here**
private void Client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
{
if (Mcallback != null) // always null here **
Mcallback.call_queryEvent();
}
}
Vm class:
using MqttInterface;
namespace oadr2b_ven.ven
{
public class VenWrapper : resources.ISendReport,MqttInterface.InterfaceClass
{
public void call_queryEvent()
{
queryEvents();
}
}
}
now the interface class:
namespace MqttInterface
{
public interface InterfaceClass
{
void call_queryEvent();
}
}
so the issue is that if I don't declare in mqtt class a object the projects runs withour error but Mcallback != null is always null.
so I decide to create a interface object and I do this.
InterfaceClass Mcallback = new MqttControllerClass();
which throws me the below error
Cannot implicitly convert type 'MqttBroker.MqttControllerClass' to 'MqttInterface.InterfaceClass'. An explicit conversion exists (are you missing a cast?
I ask you guys I am new to c#. what am I dong wrong ? is there a better method ?
let me know. thanks.
I found the answer. all you have to do is assign the object of interfaced class using a callback method to the mqtt class.
namespace MqttInterface
{
public interface InterfaceClass
{
void call_queryEvent();
}
public void setCallbackHandler(InterfaceClass callbackHandler)
{
Mcallback = callbackHandler;
}// obj is assigned from Vm class
}
Your class definition is not implementing the needed interface:
public class MqttControllerClass
{
InterfaceClass Mcallback = new MqttControllerClass(); //error here**
}
You should be using:
public class MqttControllerClass : InterfaceClass
{
InterfaceClass Mcallback = new MqttControllerClass(); //error here**
}
Because if MqttControllerClassdoes not implement InterfaceClass, then you can't assign an object of type MqttControllerClass to a variable of type InterfaceClass.
This only solves the error you mentioned, but you're still dealing with badly designed code. Read on for further information.
I am wondering why you are taking this approach.
When you create an MqttControllerClass object, its Mcallback gets populated with another new MqttControllerClass object. Why???
First of all, this will create an infinite loop (every newly instantiated MqttControllerClasswill cause another new MqttControllerClass to be instantiated, thus creating an endless loop).
Disregarding the infinite loop, I don't even understand the justification for wanting to do this. It can make sense to have a class with the property of the same type, e.g. :
public class Person
{
public Person father;
public Person mother;
}
But it makes no sense to fill these properties with newly instantiated Person objects every time you instantiate a Person object.
I'm trying to learn MonoGame and I'm trying to do basic stuff and I've figured most of it out on my own but I'm getting a null pointer and I'm not sure why. I'm trying to get MainMenuScene to just draw a texture but in SceneManager currentScene keeps giving me null pointers and I have no idea why. Ill post my SceneManager code but the rest will be on github. Its not much code so it shouldnt take long if you'd look over it. I'm super confused and I'm not sure what to google to try to figure it out myself.
https://github.com/eatmykhack/MonoGame.git
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tutorial.Scenes;
class SceneManager
{
private static SceneManager instance = new SceneManager();
Scene currentScene, newScene;
Dictionary<string, Scene> sceneDirectory =new Dictionary<string, Scene>();
public static SceneManager getInstance()
{
return instance;
}
public static Scene getCurrentScene()
{
return instance.currentScene;
}
public static void changeScene(Scene scene)
{
}
public static void addScene(string sceneName)
{
instance.newScene = instance.sceneDirectory[sceneName];
}
public void update() { currentScene.Update(); }
public void draw(SpriteBatch spriteBatch) { currentScene.Draw(spriteBatch); }
public void Initialize()
{
instance.sceneDirectory["MainMenuScene"] = new MainMenuScene();
instance.currentScene = instance.sceneDirectory["MainMenuScene"];
}
public void LoadContent(ContentManager content)
{
instance.currentScene.LoadContent(content);
}
public void UnloadContent()
{
instance.currentScene.UnloadContent();
}
}
you've declared Scene as an abstract class, so you can't just use it as you're doing: Scene currentScene, newScene. (See this reference for more details on abstract classes).
Either make scene a non-abstract class type or create another class that inherits from your abstract class, looking at your code it would be something like:
public class myScene : Scene
{
public override void Update()
{
//do something
}
// etc.
}
You are getting a NullReferenceException because you are mixing static and instance fields in your code:
There are several problems:
Your SceneManager has a public constructor, but its instance method all access the same static (singleton) instance.
Your SceneManager.Draw method does not access the static instance.
Your Game class instantiates a separate ScreenManager instance, meaning the singleton is initialized, but the Games instance isn't. This is allowed because of 1.
There are several ways of fixing this:
The Preferred way: remove the static stuff from SceneManager. Your game is going to have a single instance in the Game class anyway, and you can simply pass the instance along to any scenes. A no brainer.
However, if you want to keep this class a singleton, you need to change a couple of things. People usually want this because they are too lazy to pass the SceneManager along to each scene instance. So, singletons are bad, you won't be able to unit test anything, but I believe most indie game developers don't care too much about unit testing and would be happiest if everything was static and accessible from anywhere.
Make the constructor private, so that no other class (like Game) can instantiate it. If anyone wants to access the instance, they should do it through the getInstance() method. Which, btw, might better be a property instead:
public class SceneManager
{
// private constructor means other classes cannot instantiate this
private SceneManager() { }
private static readonly SceneManager _instance = new SceneManager();
public static SceneManager Instance
{
get { return _instance; }
}
}
If you now try to pull this off in your Game class:
var sceneManager = new SceneManager();
your compiler will tell you it's not going to work that way.
Your SceneManager should only have a single static method/property: getInstance() or the Instance property like shown above. All other methods should be instance methods of that one-and-only instance, and not access the instance field at all. They are accessing that instance anyway. It is a bad idea to have instance methods access static fields:
This is wrong:
public void Initialize()
{
var mainScene = = new MainMenuScene();
instance.sceneDirectory["MainMenuScene"] = mainScene;
instance.currentScene = mainScene;
}
But this is fine (and the this keyword is redundant, of course):
public void Initialize()
{
var mainScene = = new MainMenuScene();
this.sceneDirectory["MainMenuScene"] = mainScene;
this.currentScene = mainScene;
}
Because you're going to use it like this anyway:
// you're basically doing the same thing, but
// it's immediately clear what's going on, and there
// is no room for errors:
var manager = SceneManager.Instance;
manager.Initialize();
The simplest way to ensure you're doing it right it to remove all references to instance inside the SceneManager class.
Context
I have an InteractionWindowPresenter class in charge of creating Windows. Some of them may be modal and I want to keep a counter of the number of opened modal windows in order to notify other parts of the application.
Therefore I added a _modalsCount variable to the class, updated whenever a modal window is opened or closed:
public class InteractionWindowPresenter<TWindow, TNotification>
where TWindow : System.Windows.Window
where TNotification : Prism.Interactivity.InteractionRequest.INotification
{
private static int _modalsCount = 0;
...
private bool _useModalWindow;
public InteractionWindowPresenter(InteractionRequest<TNotification> request,
bool useModalWindow = false)
{
_useModalWindow = useModalWindow;
}
public void Show()
{
var window = ...
window.Closed += (s, e) =>
{
if (_useModalWindow)
{
_modalsCount = Math.Max(0, --_modalsCount);
if (_modalsCount == 0)
ServiceLocator.Current.GetInstance<IEventAggregator>()
.GetEvent<ModalStatusChanged>().Publish(false);
}
};
if (_useModalWindow)
{
_modalsCount++;
ServiceLocator.Current.GetInstance<IEventAggregator>()
.GetEvent<ModalStatusChanged>().Publish(true);
window.ShowDialog();
}
else
window.Show();
}
}
Upon initialization, each Prism module - ie. each class implementing IModule - instantiates an InteractionWindowPresenter per view that must be shown on a Window and holds a reference to it. For instance:
[ModuleExport("ClientsModule", typeof(Module),
DependsOnModuleNames = new[] { "RibbonModule", "ClientsModelModule" },
InitializationMode = InitializationMode.WhenAvailable)]
public class Module : IModule
{
InteractionWindowPresenter<ClientSelectionWindow, ClientSelection> _selectionPresenter;
public void Initialize()
{
_selectionPresenter =
new InteractionWindowPresenter<ClientSelectionWindow, ClientSelection>
(Interactions.ClientSelectionRequest, useModalWindow: true);
}
}
The InteractionWindowPresenter class is defined in an infrastructure assembly directly referenced by all the modules as well as other infrastructure assemblies. It is not referenced by the launcher application, which is merely a MefBootstrapper. Hence, MEF is used for composition.
The problem
Setting a breakpoint on the _modalsCount initialization line reveals that it is not executed when the InteractionWindowPresenter instances are created. Instead, it is executed the first time (and only that time) the variable is used in each module - ie. the first time the Show method is called from each module. Thus, each module has its own value, shared across all the instances of that specific module.
I understand that the lazy evaluation is due to the curious nature of beforefieldinit. However I expected that evaluation to happen just once for the whole application instead of per module.
I also tried performing the initialization in the static constructor:
static int _modalsCount;
static InteractionWindowPresenter()
{
_modalsCount = 0;
}
In this case, the static constructor is invoked prior to the execution of the instance constructor, but every single time an instance is created. Therefore, the variable seems not to be static anymore.
From my understanding, static variables are initialized once per AppDomain. Thus, since all my assemblies (modules and infrastructure) are in the same AppDomain, this should not happen. Am I wrong in any of these two assumptions?
Work-around employed so far
Creating a simple class to hold the counter avoids this problem:
static class ModalsCounter
{
private static int _modalsCount = 0;
public static int Increment()
{
return ++_modalsCount;
}
public static int Decrement()
{
_modalsCount = Math.Max(0, --_modalsCount);
return _modalsCount;
}
}
Thus replacing the calls to _modalsCount by:
ModalsCounter.Increment();
ServiceLocator.Current.GetInstance<IEventAggregator>()
.GetEvent<ModalStatusChanged>().Publish(true);
and:
if (_useModalWindow && ModalsCounter.Decrement() == 0)
ServiceLocator.Current.GetInstance<IEventAggregator>()
.GetEvent<ModalStatusChanged>().Publish(false);
So what am I missing here? Have I somehow misunderstood the lifecycle and scope of static variables or are Prism modules and/or MEF messing with me?
The static is created once for each Type. Since you are using a Generic Type the number of Types created will be equivalent to the number of combinations of Type variables you use in the initializer. This is why hiding the static inside a non generic class works (probably a better pattern anyhow).
You class is generic, and each constructed generic type (with type arguments specified) is a separate type. Each of them has its own set of static members.
From C# language specification, section 4.4.2 Open and closed types:
Each closed constructed type has its own set of static variables, which are not shared with any other closed constructed types. Since an open type does not exist at run-time, there are no static variables associated with an open type.
You can make a simple test:
public class Test<T>
{
public static object obj = new object();
}
Console.WriteLine(object.ReferenceEquals(Test<string>.obj, Test<object>.obj)); // false
Your workaround (keeping the static counter in a non-generic class) is correct.
Having read the access modifiers in C# progamming tutorial, I come to conclusion that defining a method public is enough for it to be "seen" from another Form of the same namespace.
However, in practise whenever I tried to implement this, I also had to define the method as static in order for it to be referenced from other Forms of the same namespace.
Am I loosing something?
I am doing somethning wrong?
For a public static method, you don't need a reference to an object. The method is static and can be accessed on class level.
If you can't access a public method, then you need a reference to the object, then you can.
public class AClass
{
public void DoSomething() {}
public static void DoSomethingElse() {}
}
You can use them as follows:
AClass.DoSomethingElse(); // no object reference required
AClass.DoSomething(); // will give compiler error, since you have no object reference.
var anObject = new AClass();
anObject.DoSomething(); // will work fine.
anObject.DoSomethingElse(); // compile error (thx hvd).
public static method do not need object instance, they can be used without creating any instance of the class
ClassName.MyStaticPublicMethodName()
where as public (non-static) method require an Instance of the Class, public (non-static) method in general helps you to work with the data member (field) of the object.
To use a non-static public method you need to create instance of the class
ClassName obj = new ClassName();
obj.MyPublicMethod();