labbbirder / UnityInjection

Unity DLL注入,支持全平台,支持Mono和IL2CPP,支持注入引擎和用户DLL。可以实现AOP、装饰器等功能
MIT License
115 stars 14 forks source link

可以注入并使用一些字段吗? #6

Open xzaxzaazx opened 2 months ago

xzaxzaazx commented 2 months ago

在注入方法的时候需要一些额外字段的支持,该怎么操作?

labbbirder commented 2 months ago

我不太确定你想要额外字段是哪种形式。

如果是元数据意义上的额外成员,那么很遗憾,无法实现,这是任何注入库都在避免实现的功能。btw,这个需求在某些情况下可以使用源生成解决。

如果你只是想通过增加几个变量来影响方法的行为,那么可以使用闭包来实现;如果你希望变量的生命周期关系与一个实际绑定,那么可以通过一个全局字典来实现(小心内存泄漏,同时应避免在unity中使用ConditionalWeakTable)

xzaxzaazx commented 2 months ago

我想实现类似Auto-Implemented Property的一些功能,我也想过全局字典,如果对static的字段还好说,但如果对每个instance都用字典处理是不是有点复杂?我看到InjectHelper里有注入field的步骤,是否可以做成一些工具开放?

labbbirder commented 2 months ago

可否通过例子来说明

xzaxzaazx commented 2 months ago

例如一个属性

string name=>$"{lastName} {firstName}";

我希望它的getter在第一次调用后固化在一个field里,那样需要额外写一个string的field和一个bool去存储是否第一次调用,我觉得这样写一堆参数很影响代码的直观 于是我希望通过注入达到这样的效果:

[Const]string name=>$"{lastName} {firstName}";

将这个属性注成这样:

string name{get{
     if(!name_loaded_UID)name_data_UID=$"{lastName} {firstName}";
     return name_loaded_UID;
}}
bool name_loaded_UID;
string name_data_UID;

而这需要一个类似于现在InjectionInfo.Create的东西,也许长这样:

public static InjectionInfo CreateField(Type type, string fieldName, Action<FieldInfo> fieldReceiver);

labbbirder commented 2 months ago

暴露LowLevel接口是可行的方法,这个后面会考虑。

对于这里的具体问题,事实上是cache功能。可以推广到任意有返回值的函数调用,字段取值操作是前者的子集。使用全局缓存表看起来是一个正确的选择,一个ConditionalWeakTable的临时平替可以实现为: