Extend CLR class, or overwrite functionality #1479
-
Have a 'LocaleString' class, supplier provided, not sealed. This contains strings in multiple languages with a Example: LocaleString localeString;
CultureInfo cultureInfo = new("en");
localeString[cultureInfo] = "Text in English"; The problem is a CultureInfo class is not defaultly available, and a hassle to implement, and use in JavaScript. I would like to replace the CultureInfo part with a string, like "en" and make it work. This is a snippet of the supplier provided code: public class LocaleString : ICloneable {
private Dictionary<CultureInfo, string> stringMap;
public string this[CultureInfo ci] {
get {
if (stringMap != null && ci != null && stringMap.ContainsKey(ci)) {
return stringMap[ci];
}
return null;
}
set {
lock (this) {
if (stringMap == null) {
stringMap = new Dictionary<CultureInfo, string>();
}
stringMap[ci] = value;
}
}
}
} I've tried overwriting it, with a string 'accessor', but overwriting might not work :) public class JintLocaleString : LocaleString
{
public string this[string languageCode]
{
get {
CultureInfo cultureInfo = new(languageCode);
if (ContainsCulture(cultureInfo)) return base[cultureInfo];
return null;
}
set {
base[new(languageCode)] = value;
}
}
} And registering it: jintEngine.SetValue(typeof(LocaleString).FullName, TypeReference.CreateTypeReference(jintEngine, typeof(JintLocaleString))); This doesn't work. Is there any way this can be overwritten somehow? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 5 replies
-
How does it not work? |
Beta Was this translation helpful? Give feedback.
-
I called a function in JavaScript on another object which returns a LocaleString instance and tried to access a text through Does the jintEngine.SetValue 'replaced' the implementation of the supplier I'll do more tests hopefully tomorrow morning. |
Beta Was this translation helpful? Give feedback.
-
Sorry, I meant monday morning. This is a full sample to reproduce. What I would like it to change this behavior, but I'm not sure this is possible with Jint. Else it will be hard as I need to 'proxy' all calls to the underlying objects provided by the supplier of the library. What I get is System.ArgumentException, "Expected string but got Undefined". What I expect is that it would return "English text". ConsoleApp_20230306_0843_JintReproduce.zip using Jint;
using Jint.Native;
using Jint.Runtime.Interop;
using System.Globalization;
Engine jintEngine = new();
jintEngine.SetValue(typeof(LocaleString).FullName, TypeReference.CreateTypeReference(jintEngine, typeof(JintLocaleString)));
JsValue testFunction = jintEngine.Execute(
"""
function test(localeString) {
return localeString['en'];
}
""").GetValue("test");
LocaleString localeString = new();
localeString[new CultureInfo("en")] = "English Text";
localeString[new CultureInfo("nl")] = "Nederlandse tekst";
JsValue jsValue = jintEngine.Invoke(testFunction, localeString);
Console.WriteLine(jsValue.AsString());
Console.ReadKey();
public class JintLocaleString : LocaleString {
public string this[string languageCode] {
get {
CultureInfo cultureInfo = new(languageCode);
if (ContainsCulture(cultureInfo)) {
return base[cultureInfo];
}
return null;
}
set {
CultureInfo cultureInfo = new(languageCode);
base[cultureInfo] = value;
}
}
} |
Beta Was this translation helpful? Give feedback.
-
I'm guessing what you want is a [Fact]
public void Test()
{
var engine = new Engine(o => o.AddObjectConverter(new ExternalLocaleStringConverter()));
engine.SetValue("locale", new ExternalLocaleString());
Assert.Equal("English", engine.Evaluate("locale['en']").AsString());
Assert.Equal("Dutch", engine.Evaluate("locale['nl']").AsString());
}
public class ExternalLocaleStringConverter : IObjectConverter
{
public bool TryConvert(Engine engine, object value, [NotNullWhen(true)] out JsValue result)
{
if (value is ExternalLocaleString localeString)
{
result = JsValue.FromObject(engine, new ExternalLocaleStringWrapper(localeString));
return true;
}
result = null;
return false;
}
private class ExternalLocaleStringWrapper
{
private readonly ExternalLocaleString _externalLocaleString;
public ExternalLocaleStringWrapper(ExternalLocaleString externalLocaleString)
{
_externalLocaleString = externalLocaleString;
}
public string this[string arg]
{
get
{
CultureInfo cultureInfo = new(arg);
return _externalLocaleString[cultureInfo];
}
set
{
CultureInfo cultureInfo = new(arg);
_externalLocaleString[cultureInfo] = value;
}
}
}
}
public class ExternalLocaleString
{
public string this[CultureInfo arg]
{
get => arg.DisplayName;
set { }
}
} |
Beta Was this translation helpful? Give feedback.
I'm guessing what you want is a
IObjectConverter
.