如何修改Metadata.xml使Xamarin.Android绑定AAR库生成可编译的C#泛型代码?
解决Xamarin.Android绑定库中Java协变返回类型的C#适配问题
我帮你搞定这个问题!Java支持返回类型协变(子类实现父接口时可以用子类类型覆盖父接口的返回类型),但C#不允许这种写法,不过通过修改绑定库的Metadata.xml配置,我们可以把IGetter转换成泛型接口,让生成的代码完全符合C#规范。
具体的Metadata.xml配置
首先,在你的绑定库项目中找到(如果没有就手动创建)Transforms/Metadata.xml文件,添加以下配置(记得把你的包名替换成原Java代码对应的实际包名,比如com.yourcompany.yourlibrary):
<metadata> <!-- 给IGetter接口添加泛型参数T,约束T继承自IParent --> <attr path="/api/package[@name='你的包名']/interface[@name='IGetter']" name="genericArguments"> <type-param name="T" extends="IParent" /> </attr> <!-- 将IGetter中Attribute属性的返回类型改为泛型T --> <attr path="/api/package[@name='你的包名']/interface[@name='IGetter']/method[@name='getAttribute' and return='IParent']" name="return">T</attr> <!-- 修改MyClass实现的接口为IGetter<IChild> --> <attr path="/api/package[@name='你的包名']/class[@name='MyClass']/implements[@name='IGetter']" name="name">IGetter<IChild></attr> </metadata>
配置逻辑解释
我们分三步调整生成规则:
- 将IGetter转为泛型接口:第一个
<attr>标签给IGetter添加了泛型参数T,并指定T必须继承自IParent,对应C#中的IGetter<T> where T : IParent。 - 适配接口属性的返回类型:第二个
<attr>标签把原接口中返回IParent的getAttribute方法(Java属性对应C#的get访问器)的返回类型改成泛型T,让接口属性变为T Attribute { get; }。 - 修改类的接口实现声明:第三个
<attr>标签把MyClass实现的接口从IGetter替换为IGetter<IChild>,这样MyClass的IChild Attribute属性就完全符合C#的接口实现规范了。
验证修改效果
清理并重新生成你的绑定库,生成的代码就会和你期望的一致:
public interface IParent { } public interface IChild : IParent { } public interface IGetter<T> where T : IParent { T Attribute { get; } } public class MyClass : IGetter<IChild> { public IChild Attribute { get; } }
内容的提问来源于stack exchange,提问作者Maxime Esprit
相关产品推荐
相关产品推荐

