Au moment de l’exécution, j’obtiens une instance de type quelconque. Comment décompresser le type sous-jacent?
Object obj; Ssortingng variable = "Some text"; obj = variable // boxing; // explicit unboxing, because we know the type of variable at comstack time. var x = (Ssortingng)obj // Now let's pretend that we don't know the type of underlying object at comstack time. Type desiredType = obj.GetType(); // But we can figure out. //And now the question. //How to express something like this: var y = (desiredType)obj; //Need to get unboxed instance of initial variable here;
Si vous ne connaissez pas le type au moment de la compilation , vous ne pouvez pas décompresser car vous n’avez nulle part où le placer . Tout ce que vous pouvez faire est de le stocker dans un object
, qui est: boxed.
Il en va de même pour les types de référence tels que ssortingng
: vous ne pouvez pas le convertir au bon type si vous ne connaissez pas le type au moment de la compilation: vous n’avez nulle part où le mettre .
Vous pouvez mettre en casse quelques types, par exemple:
if(obj is int) { int i = (int)obj; ... } ...
Une autre astuce qui est parfois (pas souvent) utile est de passer aux génériques . alors au lieu de parler en termes d’ object
vous parlez en termes de T
Cela a … un usage limité cependant. Le moyen le plus simple de le faire consiste à utiliser dynamicment , par exemple:
dynamic obj = ... Foo(obj); ... Foo(T val) { ... code with T ... }
vous pouvez également append des cas spéciaux à cette approche:
Foo(ssortingng val) { ... code with ssortingng ...} Foo(int val) { ... code with int ...}
Cependant, franchement, je suggère qu’il soit peut-être préférable de regarder de près ce que vous essayez de faire.
Supposons maintenant que la vraie boxe se produise:
int v = 5; object o = v; //boxed Type type = o.GetType(); //will return typeof(int) int convertedBack = (int)Convert.ChangeType(o, type); Console.WriteLine (convertedBack); //prints 5
Remarque, si vous remplacez:
object convertedBack = Convert.ChangeType(o, type); Console.WriteLine (convertedBack); //it still prints 5 Console.WriteLine (o); //it even print 5 here
La raison en est que l’object sous-jacent est toujours int
. Je viens d’utiliser cet exemple pour vous montrer que la boxe n’a aucune pertinence ici. Vous devez vous fier à une certaine abstraction dans vos opérations et si vous voulez utiliser dynamicment le int
vers int
, quel type de référence voulez-vous utiliser?
Dans de tels cas, je vais utiliser le modèle de stratégie en utilisant un Dictionary
:
internal class Program { private static void Main(ssortingng[] args) { var something = new Something(); something.ComputeValue(13); something.ComputeValue(DateTime.Now); something.ComputeValue(DayOfWeek.Monday); Console.ReadKey(); } } internal class Something { private static Dictionary> _Strategies; static Something() { // Prepare all available strategies. _Strategies = new Dictionary>(); _Strategies.Add(typeof(int), ComputeInteger); _Strategies.Add(typeof(DateTime), ComputeDateTime); } public void ComputeValue(object value) { Action
Voici un exemple de exactement pourquoi vous feriez cela:
class MyClass { public int Id {get;set;} public ssortingng Name {get;set;} public decimal Val {get;set;} } int i = 0; var myClassImp = new MyClass(); foreach (var val in new [object]{"10", "My name", "100.21"} // Could be read from some data source, such as an excel spreadsheet { var prop = typeof(MyClass).GetProperties().ElementAt(i++); // !!!!!! THROWS EXCEPTION !!!!!!! prop.SetValue(myClassImp, System.Convert.ChangeType(val, prop.PropertyType), null); }
La raison en est que la valeur est un object encadré … au moment de l’exécution, vous ne connaissez pas le type, vous devez donc décompresser le prop.PropertyType
Une solution pragmatique; essayez d’utiliser un TypeConverter directement, et si cela échoue, convertissez-le en chaîne et inversement: –
private static T GetValueOfType(this ManagementBaseObject MBO, Ssortingng FieldName) { T lResult; try { Object lObj = MBO[FieldName]; var lSrcType = lObj.GetType(); var lDestType = typeof(T); if (lDestType.IsValueType && lDestType.IsAssignableFrom(lSrcType)) { lResult = (T)lObj; return lResult; } var lDestTC = TypeDescriptor.GetConverter(typeof(T)); if (lDestTC.CanConvertFrom(lSrcType)) { lResult = (T)lDestTC.ConvertFrom(lObj); } else { var lSrcTC = TypeDescriptor.GetConverter(lSrcType); Ssortingng lTmp = lSrcTC.ConvertToInvariantSsortingng(lObj); lResult = (T)lDestTC.ConvertFromInvariantSsortingng(lTmp); } } catch { lResult = default(T); } return lResult; }
public static ssortingng GetType(object data) { Type type = data.GetType(); return Convert.ChangeType(data, type).GetType().Name; }
Bonjour, cette méthode reçoit les données d’object et retourne le nom du type de chaîne de l’object. J’espère que c’est ce dont vous avez besoin.
Utiliser des expressions:
var y = DynamicCast (obj, désiréType);
static object DynamicCast(object source, Type type) { var parameter = Expression.Parameter(typeof(object), "input"); var cast = Expression.TypeAs(Expression.Convert(parameter, type), typeof(object)); var lambda = Expression.Lambda>(cast, parameter); var func = lambda.Comstack(); return func(source); }
vous pouvez essayer d’utiliser le runtime dynamic
[Test] public void Test_UnboxingAtRuntime() { object boxed = "Hello"; //this line is commented out as it does not comstack // OverloadedMethod(boxed); var result = CallCorrectMethod(boxed); Assert.That(result, Is.EqualTo("ssortingng")); boxed = 1; result = CallCorrectMethod(boxed); Assert.That(result, Is.EqualTo("int")); } public ssortingng CallCorrectMethod(dynamic t) { return OverloadedMethod(t); } public ssortingng OverloadedMethod(ssortingng s) { return "ssortingng"; } public ssortingng OverloadedMethod(int s) { return "int"; }