- Home /
3 Days and I still can't figure out c# reflection, please help? Trying to use a protected Type and method.
Unity's source code for the type I need can be viewed here: DockArea.cs
I'm actually trying to use the "addTab" method metionned in DockArea.cs (Note: I cannot use GetWindow, it doesn't allow creating multiple windows of the same type and is the only way to specify a tab placement
My code so far (for add tab):
public static void DockTab(this EditorWindow anchor, EditorWindow docked) {
var addTab = anchor.GetType().GetMethod("AddTab", BindingFlags.Instance | BindingFlags.Public);
object[] param = {docked};
addTab.Invoke(docked, param);
}
And it gives the following error:
NullReferenceException: Object reference not set to an instance of an object
Rethrow as TargetInvocationException: Exception has been thrown by the target of an invocation.
I think the problem may be that I'm trying to use add tab the wrong way, in EditorWindow.cs there is an example of how it's used. Been trying for days to make it work but I have no clue what I'm doing when it comes to reflection. Tried some tutorials but I still dont get it.
Please help.
UPDATE:
Here is another piece of code I tried (based on EditorWindow.cs) but I get stuck at accessing w.rootView.allChildren and will still need the DockArea type and it still not the proper usage as it would have to run this from withing the editor window being docked... I think.
public static System.Type[] GetAllDerivedTypes(this System.AppDomain aAppDomain, System.Type aType) {
var result = new List<System.Type>();
var assemblies = aAppDomain.GetAssemblies();
foreach (var assembly in assemblies) {
var types = assembly.GetTypes();
foreach (var type in types) {
if (type.IsSubclassOf(aType))
result.Add(type);
}
}
return result.ToArray();
}
public static void DockTab(Type desired) {
var containerWinType = System.AppDomain.CurrentDomain.GetAllDerivedTypes(typeof(ScriptableObject)).Where(t => t.Name == "ContainerWindow").FirstOrDefault();
if (containerWinType == null)
throw new System.MissingMemberException("Can't find internal type 'ContainerWindow'.");
var windows = Resources.FindObjectsOfTypeAll(containerWinType);
foreach (var w in windows) {
var rootviewProperty = containerWinType.GetProperty("rootView", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
// var allChildren = rootviewProperty.get
foreach (var view in w.rootView.allChildren)s
{
var dockArea = view as DockArea;
if (dockArea == null) continue;
if (dockArea.m_Panes.Any(pane => pane.GetType() == desired))
{
dockArea.AddTab(win);
}
}
}
}
Maybe its possible to override GetWindow (anothing thing I dont know how to use) to somehow prevent GetWindow from checking if a window of the requested type allready exist. If I can force it to open a new window everytime that would also work.
Why is it so important if I may ask that you dock to Unity's existing dock system? Couldn't you create your own docking system? If you're trying to open multiples of the same editor window, then this sounds like you just need to have a logical way of displaying multiple of the same idea, in the same window. $$anonymous$$ake your own tab system in your editor window, and make your window extendable, so you don't need 2 windows, but can do the process of 2 windows in 1 window, or the process of infinite windows in 1 window.
I am making a management software. The ability to open multiple views of different items simultaneously is required. Seems much easier to use the built in Windows and tab system than whipping my own.
You say that, but you'd of already created your own tab system by now. Not that theres anything wrong with your approach, I just think since Unity doesn't expose it's classes, it would be easier to control something you created.
EDIT: You may find this to be useful Docking Editor Windows Side by Side Via Script
var addTab = anchor.GetType().Get$$anonymous$$ethod(...
but anchor
is a EditorWindow
Type, not a DockArea
Type. Based on the link you provided, it looks like the function you're trying to find is a member of the DockArea class.
Are you sure you are even getting the correct function back from this line?
I'd expect you want to use the m_Parent
member of your anchor EditorWindow, which is a HostView
type, and $$anonymous$$AY have been instantiated as a DockArea
.
Answer by Bunny83 · Apr 06, 2019 at 06:15 PM
As Glurth already mentioned in the comment above your anchor is an EditorWindow, not a DockArea. The EditorWindow class is actually the lowest child of the hierarchy. So it's essentially the "content" of the window. An EditorWindows, in order to be visible, need to be "placed" in a HostView. The HostView an editor window belongs to is also stored in an internal field of the EditorWindow class (m_Parent). Also as Glurth said you can never be sure what type of HostView an EditorWindow is part of until you check the type. There are the classes HostView, SplitView, DockArea, MainView (any maybe others) which build up the hierarchy of the layout of an actual single window. The top most class is usually a ContainerWindow when you have a floating window. If the view is part of the editor main window that's another special case.
I suggest you first examine which classes you have to deal with. Manipulating the layout system of the editor is really a pain as almost every relevant class is internal. So you need a bit more reflection than those few things you currently have. Note that to use reflection in a more efficient way you want to cache the MethodInfos
I want to thank you both @Glurth and @Bunny83 for your explanation of what was going on. I took another go at analysing working reflection code and finally understood how to do the required casting dance to get everything working. Thought I had issues with the bindingflags but found out my issues were caused by incorrect types I had set for the AddTab $$anonymous$$ethod.
Thanks you all!
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Maintain local transform.rotation.y when updating transform.up? 2 Answers
How to unfreeze a Script in a unity5 Scene? 1 Answer
How to automate unity editor screen grabs 0 Answers
My Script Wont work? 2 Answers