-
Hi y'all, loving Jint so far! Though I'm stuck atm. I'm trying to make it so when I expose objects to JS, I can specify which members can be accessed from JS by adding a "[ScriptAccessible]" attribute. I can make this work for fields and properties, but am unsure how to approach returning a Method as a JsValue. My setup: var engine = new Engine((_, opts) =>
{
opts.SetMemberAccessor(GetObjectMember);
});
// [...]
// Hides anything that isn't tagged with [ScriptAccessible]
// Ensures lowerCamelCase is converted to UpperCamelCase
private static JsValue GetObjectMember(Engine engine, object target, string memberName)
{
var builder = new StringBuilder();
builder.Append(char.ToUpper(memberName[0]));
if (memberName.Length > 1)
builder.Append(memberName.Substring(1));
var upperCamelCaseMemberName = builder.ToString();
var type = target.GetType();
var members = type.GetMember(upperCamelCaseMemberName);
MemberInfo targetMember = null;
for (var i = 0; i < members.Length; i++)
{
if (members[i].GetCustomAttribute<ScriptAccessibleAttribute>() != null)
if (targetMember == null)
targetMember = members[i];
else
// TODO: Implement checking overloaded method somehow
throw new NotImplementedException($"Members name ambigous. Multiple members with name `{upperCamelCaseMemberName}` are marked [ScriptAccessible].");
}
// If no members exist marked [ScriptAccessible], do not allow accessing them
if (targetMember == null)
return JsValue.Undefined;
switch (targetMember.MemberType)
{
case MemberTypes.Field:
return JsValue.FromObject(engine, ((FieldInfo)targetMember).GetValue(target));
case MemberTypes.Property:
return JsValue.FromObject(engine, ((PropertyInfo)targetMember).GetValue(target));
case MemberTypes.Method:
return ???; // Return the method somehow?
default:
throw new NotImplementedException("Can't access this type of member from JS yet!");
}
} How can I return a method from C# such that it can be called in JavaScript? I feel like the classes and methods I could use are marked internal or private so it seems I have to rewrite/copy a lot. Anyone got an idea or pointers? |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 6 replies
-
Things are usually internal and hidden to allow some room for change. In your case I think you're after a filter/predicate that could be called to verify whether member should be resolved? I guess there's no such thing at the moment, but there's been an ask to hide |
Beta Was this translation helpful? Give feedback.
-
I've found a way to return the method using ClrFunctionInstance. It was easier than it seemed though I'm not sure if there's a better way: return new ClrFunctionInstance(engine, memberName, (thisObject, arguments) =>
{
return CallMethod(engine, method, methodParameters, (ObjectWrapper)thisObject, arguments);
}, methodParameters.Length, PropertyFlag.Configurable); // Why PropertyFlag.Configurable?? No idea. I uploaded the full code to this gist for future reference. Maybe it can help someone. |
Beta Was this translation helpful? Give feedback.
I've found a way to return the method using ClrFunctionInstance. It was easier than it seemed though I'm not sure if there's a better way:
I uploaded the full code to this gist for future reference. Maybe it can help someone.