Open david-obee opened 1 year ago
the same behavior (I may be wrong though in explaining) exists even without surrogates, to reproduce I simply need some base class in the same project, e.g.
interface IObj<out T> { }
class BaseObj<T1, T2> : IObj<T> { /*properties*/ }, t1 and t2 are primitives
class Obj : BaseObj<long, int>
and if I do grainMethod<T>(IObj<T> obj)
with Obj object
as input parameter I get the same error as you do, inspecting in the debugger and I see that one generic argument is missing, does not matter which serializer I use, neither built-in one with GenerateSerializer attribute or SystemTextJson serializer work (but as I see the error appears way before serialization, so just two cents)
for now my solution is to avoid generics usage, so I had to rewrite 1000 classes (uh, I want to migrate to Orleans 7 hehe)
I'm running into an issue with using surrogate types for an external type, which is generic, but which has a sub-type which is not generic. Reading the documentation, it sounded like my use case would be supported, but I think it's really only in a restricted subset of scenarios that using generic surrogates works.
In my use case, I have in the external library (that should not take a dependency on Orleans):
I then have in my assembly (which is then using Orleans), the sub-type, surrogate, and surrogate converter defined:
The issue I have is that I get the error
System.ArgumentException: The number of generic arguments provided doesn't equal the arity of the generic type definition. (Parameter 'instantiation')
at this point in the OrleansCodecProvider
code:https://github.com/dotnet/orleans/blob/v7.1.0/src/Orleans.Serialization/Serializers/CodecProvider.cs#L559
When searching for
fieldType
ofIntId
, we reach the point wheresearchType
isSomeId`1[T]
, for which we have a key in_converters
, and the value is thenSomeIdSurrogateConverter`1[T]
. So far so good, it means we've correctly searched up the type hierarchy until we find our converter for the base type.The issue is that then on line 559, where we call
converterType.MakeGenericType(fieldType.GetGenericArguments())
. Here,fieldType
is not generic, soGetGenericArguments
returns an empty array. In fact, this will always fail so long as the derivedfieldType
has a different number of generic parameters than thesearchType
. It should never have more generic parameters, but it seems reasonable that it might have fewer.This might be too niche a use case to want to support in the serializer. I think I can work around it by introducing non-generic intermediaries, which can then have non-generic type converters, but this isn't ideal. It would be great if the serializer could figure out the type parameters of the base type, in the case that the derived type isn't generic and specifies the type parameters as part of it's definition. I am conscious though that that might incur quite a bit of additional complexity. In that case, it might be valuable to expand the documentation instead to make clear the restrictions, i.e. derived types need the same number of generic parameters, and they must be in the same order as the base type.
Thanks!