将泛型<TObject>类传递给表单

Dav*_*y C 10 c# forms generic-programming tobject

我似乎无法通过搜索找到答案,所以这里......

我知道我可以通过利用这种类型的代码将Class对象一般传递给其他类:

public class ClsGeneric<TObject> where TObject : class
{
    public TObject GenericType { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后以这种方式构建:

ClsGeneric<MyType> someName = new ClsGeneric<MyType>()
Run Code Online (Sandbox Code Playgroud)

但是,我有一个应用程序,要求我打开一个表单,并以某种方式传递泛型类型以便在该表单中使用.我试图能够为许多不同的类类型重用此表单.

有谁知道这是否可能,如果可能,如何?

我已经使用Form构造函数进行了一些实验,但无济于事.

非常感谢,戴夫

更新:澄清我想要达到的结果是什么

在此输入图像描述

更新:今年4月4日,我进一步前进,但我提供了解决方案的赏金.这就是我现在拥有的:

interface IFormInterface
{
    DialogResult ShowDialog();
}


public class FormInterface<TObject> : SubForm, IFormInterface where TObject : class
{ }

public partial class Form1 : Form
{
    private FormController<Parent> _formController;

    public Form1()
    {
        InitializeComponent();
            _formController = new FormController<Parent>(this.btnShowSubForm, new DataController<Parent>(new MeContext()));   
    }
}

public class FormController<TObject> where TObject : class
{
    private DataController<TObject> _dataController;
    public FormController(Button btn, DataController<TObject> dataController)
    {
        _dataController = dataController;
        btn.Click += new EventHandler(btnClick);
    }

    private void btnClick(object sender, EventArgs e)
    {
        showSubForm("Something");
    }

    public void showSubForm(string className)
    {
        //I'm still stuck here because I have to tell the interface the Name of the Class "Child", I want to pass <TObject> here.
        // Want to pass in the true Class name to FormController from the MainForm only, and from then on, it's generic.

        IFormInterface f2 = new FormInterface<Child>();
        f2.ShowDialog();
    }
}

class MeContext : DbContext
{
    public MeContext() : base(@"data source=HAZEL-PC\HAZEL_SQL;initial catalog=MCL;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework") { }
    public DbSet<Parent> Child { get; set; }
}

public class DataController<TObject> where TObject : class
{
    protected DbContext _context;

    public DataController(DbContext context)
    {
        _context = context;
    }
}

public class Parent
{
    string Name { get; set; }
    bool HasChildren { get; set; }
    int Age { get; set; }
}

public class Child
{
    string Name { get; set; }
    int Age { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Gui*_*rme 10

也许你已经尝试过了,但是你可以创建一个自定义类:

public class GenericForm<TObject> : Form where TObject : class
{
    // Here you can do whatever you want,
    // exactly like the example code in the
    // first lines of your question
    public TObject GenericType { get; set; }

    public GenericForm()
    {
        // To show that this actually works,
        // I'll handle the Paint event, because
        // it is executed AFTER the window is shown.
        Paint += GenericForm_Paint;
    }

    private void GenericForm_Paint(object sender, EventArgs e)
    {
        // Let's print the type of TObject to see if it worked:
        MessageBox.Show(typeof(TObject).ToString());
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您创建它的实例:

var form = new GenericForm<string>();
form.Show();
Run Code Online (Sandbox Code Playgroud)

结果是:

在此输入图像描述

更进一步,您可以使用以下类TObjectGenericForm类中创建类型实例Activator:

GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
Run Code Online (Sandbox Code Playgroud)

在这个例子中,因为我们知道这是一个字符串,我们也知道它应该抛出异常,因为string没有无参数构造函数.所以,让我们使用char array(char[])构造函数:

GenericType = (TObject)Activator.
         CreateInstance(typeof(TObject), new char[] { 'T', 'e', 's', 't' });

MessageBox.Show(GenericType as string);
Run Code Online (Sandbox Code Playgroud)

结果:

在此输入图像描述

那我们做功课吧.以下代码应该实现您想要做的.

public class Parent
{
    string Name { get; set; }
    bool HasChildren { get; set; }
    int Age { get; set; }
}

public class Child
{
    string Name { get; set; }
    int Age { get; set; }
}

public class DataController<TObject> where TObject : class
{
    protected DbContext _context;

    public DataController(DbContext context)
    {
        _context = context;
    }
}

public class FormController<TObject> where TObject : class
{
    private DataController<TObject> _dataController;

    public FormController(Button btn, DataController<TObject> dataController)
    {
        _dataController = dataController;
        btn.Click += new EventHandler(btnClick);
    }

    private void btnClick(object sender, EventArgs e)
    {
        GenericForm<TObject> form = new GenericForm<TObject>();
        form.ShowDialog();
    }
}

public class GenericForm<TObject> : Form where TObject : class
{
    public TObject GenericType { get; set; }

    public GenericForm()
    {
        Paint += GenericForm_Paint;
    }

    private void GenericForm_Paint(object sender, EventArgs e)
    {
        MessageBox.Show(typeof(TObject).ToString());

        // If you want to instantiate:
        GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,查看当前的示例,您有两个类,Parent并且Child.如果我理解正确,那些是唯一的可能性TObject.

如果是这种情况,那么如果有人传递a string作为类型参数(当执行到达时Activator.CreateInstance),上面的代码将会爆炸- 带有运行时异常(因为string没有无参数构造函数):

在此输入图像描述

为了保护您的代码,我们可以在可能的类中继承接口.这将导致编译时异常,这是更可取的:

在此输入图像描述

代码如下.

// Maybe you should give a better name to this...
public interface IAllowedParamType { }

// Inherit all the possible classes with that
public class Parent : IAllowedParamType
{
    string Name { get; set; }
    bool HasChildren { get; set; }
    int Age { get; set; }
}

public class Child : IAllowedParamType
{
    string Name { get; set; }
    int Age { get; set; }
}

// Filter the interface on the 'where'
public class DataController<TObject> where TObject : class, IAllowedParamType
{
    protected DbContext _context;

    public DataController(DbContext context)
    {
        _context = context;
    }
}

public class FormController<TObject> where TObject : class, IAllowedParamType
{
    private DataController<TObject> _dataController;

    public FormController(Button btn, DataController<TObject> dataController)
    {
        _dataController = dataController;
        btn.Click += new EventHandler(btnClick);
    }

    private void btnClick(object sender, EventArgs e)
    {
        GenericForm<TObject> form = new GenericForm<TObject>();
        form.ShowDialog();
    }
}

public class GenericForm<TObject> : Form where TObject : class, IAllowedParamType
{
    public TObject GenericType { get; set; }

    public GenericForm()
    {
        Paint += GenericForm_Paint;
    }

    private void GenericForm_Paint(object sender, EventArgs e)
    {
        MessageBox.Show(typeof(TObject).ToString());

        // If you want to instantiate:
        GenericType = (TObject)Activator.CreateInstance(typeof(TObject));
    }
}
Run Code Online (Sandbox Code Playgroud)

UPDATE

正如RupertMorrish所说,您仍然可以编译以下代码:

public class MyObj : IAllowedParamType
{
    public int Id { get; set; }

    public MyObj(int id)
    {
        Id = id;
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该仍然会引发异常,因为您刚刚删除了隐式无参数构造函数.当然,如果你知道你在做什么,这很难发生,但是我们可以通过使用new()'where'类型过滤来禁止这一点- 同时也摆脱了这些Activator.CreateInstance东西.

整个代码:

// Maybe you should give a better name to this...
public interface IAllowedParamType { }

// Inherit all the possible classes with that
public class Parent : IAllowedParamType
{
    string Name { get; set; }
    bool HasChildren { get; set; }
    int Age { get; set; }
}

public class Child : IAllowedParamType
{
    string Name { get; set; }
    int Age { get; set; }
}

// Filter the interface on the 'where'
public class DataController<TObject> where TObject : new(), IAllowedParamType
{
    protected DbContext _context;

    public DataController(DbContext context)
    {
        _context = context;
    }
}

public class FormController<TObject> where TObject : new(), IAllowedParamType
{
    private DataController<TObject> _dataController;

    public FormController(Button btn, DataController<TObject> dataController)
    {
        _dataController = dataController;
        btn.Click += new EventHandler(btnClick);
    }

    private void btnClick(object sender, EventArgs e)
    {
        GenericForm<TObject> form = new GenericForm<TObject>();
        form.ShowDialog();
    }
}

public class GenericForm<TObject> : Form where TObject : new(), IAllowedParamType
{
    public TObject GenericType { get; set; }

    public GenericForm()
    {
        Paint += GenericForm_Paint;
    }

    private void GenericForm_Paint(object sender, EventArgs e)
    {
        MessageBox.Show(typeof(TObject).ToString());

        // If you want to instantiate:
        GenericType = new TObject();
    }
}
Run Code Online (Sandbox Code Playgroud)


Ale*_*eev 3

我认为你可以添加一个新的类型参数FormController

public class FormController<TParent, TChild>
  where TParent : class
  where TChild : class 
{
    ...

    public void showSubForm(string className)
    {
        IFormInterface f2 = new FormInterface<TChild>();
        f2.ShowDialog();
    }
}
Run Code Online (Sandbox Code Playgroud)