TechArena Community

TechArena Community (http://forums.techarena.in/)
-   Software Development (http://forums.techarena.in/software-development/)
-   -   C # generic classes reflection (http://forums.techarena.in/software-development/1263285.htm)

Wyvern 26-10-2009 05:00 PM

C # generic classes reflection
 
I just found a fairly significant problem beginning to touch the reflection in C#, here's the context:

The purpose piece of code is to make an interface for managing I/O base (keyboard, mouse, joystick ..). Since these 3 devices are close enough the code is so I wanted to use a maximum of templates.

(I developed on XNA but for this example I did not).

So I have 2 classes:

- LocalInputManager: Undertakes to store a list of Control, modify, delete, pause etc etc.

- Control: Stock a group of keys associated with an event from another.

Here's an example:

LocalInputManager:

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestReflection
{
    public enum Keys
    {
        Left,
        Right,
        Up,
        Down,
        Space
    };
    class LocalInputManager<T, C> where C : class, new()
    {
        protected List<KeyValuePair<string, C>> controls;
        private int totalControls;
        public LocalInputManager()
        {
            this.totalControls = 0;
            this.controls = new List<KeyValuePair<string, C>>();
        }
        public void AddControl(string Name, T Keys, bool KeyRepeat)
        {
            C instance = (C)Activator.CreateInstance(typeof(C), Keys, KeyRepeat);
            this.controls.Add(new KeyValuePair<string, C>(Name, instance));
            this.totalControls++;
        }
        public void UpdateAllControls()
        {
            for (int i = 0; i < this.totalControls; i++)
            {
                this.controls[i].Value.Update();
            }
        }
    }
}

Control:

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestReflection
{
    class Control<T>
    {
        private T controls;
        private bool repeat;
        public Control()
        {
            this.repeat = false;
        }
        public Control(T Key, bool Repeat)
        {
            this.controls = Key;
            this.repeat = Repeat;
        }
        public void Update()
        {
            Console.WriteLine("Updated." );
        }
    }
}

And a small hand to test that exposes the problem:

Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestReflection
{
    class Program
    {
        static void Main(string[] args)
        {
            LocalInputManager<Keys, Control<Keys>> manager;
            manager = new LocalInputManager<Keys, Control<Keys>>();
            manager.AddControl("Running Right", Keys.Right, true);
            manager.AddControl("Skip", Keys.Space, false);
        }
    }
}

The problem lies in the class LocalInputManager in UpdateAllControls method.
Indeed, it is not the method Update () contained in C, how hard I was angry with him because C is a generic type.

So the question is: How to specify that C does have the method without specifying the type as there is more interest in this case?

opaper 26-10-2009 05:05 PM

Re: C # generic classes reflection
 
One solution (keeping the generic types), use an interface that will define the Update method. The Control class <T> then inherits this interface. And then you add this: ITonInterfaceFoo

class LocalInputManager <T, C> where C: ITonInterfaceFoo, new ()

Besides the way, you do not need to do this:
Instance = C (C) Activator.CreateInstance (typeof (C), Keys, KeyRepeat);
Knowing that you have:
class LocalInputManager <T, C> where C: ITonInterfaceFoo, new()
The new() specifies that you can instantiate the class C in LocalInputManager. You do not do it, you do CreateInstance instead, which is ugly.
Instead, you make
C instance = new C (Keys, KeyRepeat) after the manufacturer specified in the interface Foo

Wyvern 26-10-2009 05:08 PM

Re: C # generic classes reflection
 
Thank you for your quick response. Your explanation is clear and works perfectly. However I admit that it remains for me a gray area. I do not see how to declare the constructor of my class in the Control interface that describes it.

I do not control still use interfaces but as a constructor takes the name of the class I see not well what to wear.

I am trying INomInterface ([...]); good but not really believe it because it would mean that I try to instantiate the interface.

Especially since my Control class is a class template and it takes a type parameter T in a 1st of its builders.

The new keyword without additional declaration does not permit me to draw something other than the default constructor, which is quite logical.

opaper 26-10-2009 05:11 PM

Re: C # generic classes reflection
 
Quote:

Originally Posted by Wyvern (Post 4665855)
The new keyword without additional declaration does not permit me to draw something other than the default constructor, which is quite logical.

Yes oops, this is not possible because (an interface does not define a constructor). Strange, I thought I made a new set in my current project, I look at Monday.

Otherwise you can also do this:

C instance = new C ()
(
controls = Keys
Repeat = KeyRepeat
);

By fields and Repeat controls in the interface that ultimately becomes an abstract class (abstract class). This abstract class in turn becomes generic, since controls is a generic type. Everything becomes this:

Code:

class Program
    {
        static void Main(string[] args)
        {
            LocalInputManager<Keys, Control<Keys>> manager;
            manager = new LocalInputManager<Keys, Control<Keys>>();
            manager.AddControl("Running Right", Keys.Right, true);
            manager.AddControl("Skip", Keys.Space, false);
        }
    }
    public enum Keys
    {
        Left,
        Right,
        Up,
        Down,
        Space
    };
    class LocalInputManager<T, C> where C : AbstractControl<T>, new()
    {
        protected List<KeyValuePair<string, C>> controls;
        private int totalControls;
        public LocalInputManager()
        {
            this.totalControls = 0;
            this.controls = new List<KeyValuePair<string, C>>();
        }
        public void AddControl(string Name, T Keys, bool KeyRepeat)
        {
            C instance = new C()
            {
                controls = Keys,
                repeat = KeyRepeat
            };
            this.controls.Add(new KeyValuePair<string, C>(Name, instance));
            this.totalControls++;
        }
        public void UpdateAllControls()
        {
            for (int i = 0; i < this.totalControls; i++)
            {
                this.controls[i].Value.Update();
            }
        }
    }
    abstract class AbstractControl<T>
    {
        public T controls;
        public bool repeat;
        public abstract void Update();
    }
    class Control<T> : AbstractControl<T>
    {
        private new T controls;
        private new bool repeat;
        public Control()
        {
            this.repeat = false;
        }
        public Control(T Key, bool Repeat)
        {
            this.controls = Key;
            this.repeat = Repeat;
        }
        public override void Update()
        {
            Console.WriteLine("Updated." );
        }
    }



All times are GMT +5.5. The time now is 03:37 PM.