简体   繁体   中英

Using Activator.CreateInstance(Type t), how to cast 'object' to 'T' to add to List<T>

Working in a custom WPF control, we need to allow the user to add a new object to a list (similar to the ComboBox when IsEditable = true).
The ItemsSource is an ObservableCollection<T>.

When the user enters a string, the control needs to create a new T object and add it to the list.
We have a method to determine what type T is from the ItemsSource object, and then use Activator.CreateInstance() to create a T:

 private Type _typ;
 public void AddSomething(object o)
 {
     var iCollection = o as ICollection;
     if (iCollection != null)
     {
        dynamic oc = iCollection;
        _typ = GetGenericType(oc);
        Debug.WriteLine($"    ICollection<T> T type: {_typ}");

        var thng = Activator.CreateInstance(_typ);  

        Debug.WriteLine($"    thng Type: {thng.GetType()}");  
        
        ItemsSourceClass.Things.Add(thng as _typ);  
        // Compile time error:
        CS0246  The type or namespace name '_typ' could not be found (are you missing a using directive or an assembly reference?)
        /* snip */  
            

This all works as expected - thng is a new instance of T - until we try to add the new object to the ItemsSource collection.

Since Activator.CreateInstance(Type t) returns object , it seems like we need to cast thng to T to add to the ObservableCollection<T>.
We have tried various ways to convince the ItemsSource collection that thng is the correct type, but have not found one that works.
What are we missing?
Update
We added a dependency variable:

    public static readonly DependencyProperty ListObjectTypeProperty =
      DependencyProperty.Register("ListObjectType", typeof(Type), typeof(AutoCompleteComboBox));  

In xaml:

   ListObjectType="{x:Type local:SimpleClass}"

This usage of the ListObjectTypeProperty delivers the correct object, but it still is Type object :

Same result doing it this way:

   var assemName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;

   var thng = Activator.CreateInstance(assemName, ListObjectType.FullName);
   var thng2 = thng.Unwrap();

You need to use reflection to call Add also:

ItemsSourceClass.Things
    .GetType()
    .GetMethod(nameof(ItemsSourceClass.Things.Add))
    .Invoke(ItemsSourceClass.Things, new object[] { thng });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM