-
I've been reading through the NativeAOT and trimming docs, and I have some questions. Some code: using System.Diagnostics.CodeAnalysis;
EnsureCreatable<Foo<int>>(); // 1
object o = CreateFor<int>();
Use(o);
void EnsureCreatable<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>()
{ /* empty */}
object CreateFor<T>()
{
var type = typeof(Foo<>).MakeGenericType(new[] { typeof(T) });
return Activator.CreateInstance(type)!; // 2
}
void Use(object o)
{
(o as IBar)!.Baz(); // 3
}
interface IBar
{
void Baz();
}
class Foo<T> : IBar
{
public void Baz()
{
Console.WriteLine("Called");
}
} If the call to the empty method at If anywhere in the app there is a reachable user of an interface member (like |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments 8 replies
-
The type can be instantiated, yes. But there is no strong guarantee. You will still get AOT warnings in the
The implementation of that member is preserved on all instantiable types that implement it. If a type implements that interface, but nothing creates that type, the type can be trimmed. |
Beta Was this translation helpful? Give feedback.
-
By there is no strong guarantee you mean: the tooling can't guarantee that I did not forget to call My question is mostly to check that the
For the above example code, what causes |
Beta Was this translation helpful? Give feedback.
-
For the void EnsureCreatable<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>()
{
_myCache[typeof(T)] = typeof(T).GetConstructor([]);
}
object CreateFor<T>()
{
_myCache[typeof(Foo<T>)].Invoke([]);
} This way trimming can fully analyze the code. There are no warnings ( |
Beta Was this translation helpful? Give feedback.
-
I have another question. This one is about the 'viral' nature of the The following example gives warnings for the generic parameters of the using System.Diagnostics.CodeAnalysis;
Reader reader = new();
var value = reader.Read<Struct<string, Struct<int, string>>>();
Console.WriteLine(value.Item1);
Console.WriteLine(value.Item2.Item1);
Console.WriteLine(value.Item2.Item2);
ref struct Reader
{
public int ReadInt() => 42;
public string ReadString() => "foo";
public T Read<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>()
{
Type type = typeof(T);
if (type == typeof(string))
{
return (T)(object)ReadString();
}
else if (type == typeof(int))
{
return (T)(object)ReadInt();
}
else if (type.IsAssignableTo(typeof(IReadable)))
{
var readable = (Activator.CreateInstance<T>() as IReadable)!;
readable.ReadFrom(ref this);
return (T)readable;
}
ThrowNotSupportedType(type);
return default;
}
private static void ThrowNotSupportedType(Type type)
=> throw new NotSupportedException($"Cannot read type {type.FullName}");
}
struct Struct<T1, T2> : IReadable
{
public T1 Item1;
public T2 Item2;
void IReadable.ReadFrom(ref Reader reader)
{
Item1 = reader.Read<T1>();
Item2 = reader.Read<T2>();
}
}
interface IReadable
{
void ReadFrom(ref Reader reader);
} |
Beta Was this translation helpful? Give feedback.
-
@vitek-karas @eerhardt @MichalStrehovsky thanks for all your answers to my questions! I'm going to mark the first "Mark as answer" to close the workflow on this discussion. |
Beta Was this translation helpful? Give feedback.
The type can be instantiated, yes. But there is no strong guarantee. You will still get AOT warnings in the
CreateFor<T>
method. The tools can't statically guarantee it will work.The implementation of that member is preserved on all instantiable types that implement it. If a type implements that interface, but nothing creates that type, the type can be trimmed.