/* ****************************************************************************
*
* Copyright (c) Microsoft Corporation.
*
* This source code is subject to terms and conditions of the Microsoft Public License. A
* copy of the license can be found in the License.html file at the root of this distribution. If
* you cannot locate the Microsoft Public License, please send an email to
* dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
* by the terms of the Microsoft Public License.
*
* You must not remove this notice, or any other, from this software.
*
*
* ***************************************************************************/
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Remoting;
using System.Security.Permissions;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting.Utils;
using System.Linq.Expressions;
using System.Dynamic.Binders;
namespace Microsoft.Scripting.Hosting {
///
/// ObjectOperations provide a large catalogue of object operations such as member access, conversions,
/// indexing, and things like addition. There are several introspection and tool support services available
/// for more advanced hosts.
///
/// You get ObjectOperation instances from ScriptEngine, and they are bound to their engines for the semantics
/// of the operations. There is a default instance of ObjectOperations you can share across all uses of the
/// engine. However, very advanced hosts can create new instances.
///
public sealed class ObjectOperations
#if !SILVERLIGHT
: MarshalByRefObject
#endif
{
private readonly DynamicOperations _ops;
private readonly ScriptEngine _engine;
// friend class: DynamicOperations
internal ObjectOperations(DynamicOperations ops, ScriptEngine engine) {
Assert.NotNull(ops);
Assert.NotNull(engine);
_ops = ops;
_engine = engine;
}
public ScriptEngine Engine {
get { return _engine; }
}
#pragma warning disable 618
#region Local Operations
///
/// Returns true if the object can be called, false if it cannot.
///
/// Even if an object is callable Call may still fail if an incorrect number of arguments or type of arguments are provided.
///
public bool IsCallable(object obj) {
return _ops.DoOperation(StandardOperators.IsCallable, obj);
}
///
/// Calls the provided object with the given parameters and returns the result.
///
/// The prefered way of calling objects is to convert the object to a strongly typed delegate
/// using the ConvertTo methods and then invoking that delegate.
///
public object Call(object obj, params object[] parameters) {
return _ops.Invoke(obj, parameters);
}
///
/// Invokes a member on the provided object with the given parameters and returns the result.
///
public object InvokeMember(object obj, string memberName, params object[] parameters) {
return _ops.InvokeMember(obj, memberName, parameters);
}
public object CreateInstance(object obj, params object[] parameters) {
return _ops.CreateInstance(obj, parameters);
}
///
/// Gets the member name from the object obj. Throws an exception if the member does not exist or is write-only.
///
public object GetMember(object obj, string name) {
return _ops.GetMember(obj, name);
}
///
/// Gets the member name from the object obj and converts it to the type T. Throws an exception if the
/// member does not exist, is write-only, or cannot be converted.
///
public T GetMember(object obj, string name) {
return _ops.GetMember(obj, name);
}
///
/// Gets the member name from the object obj. Returns true if the member is successfully retrieved and
/// stores the value in the value out param.
///
public bool TryGetMember(object obj, string name, out object value) {
return _ops.TryGetMember(obj, name, out value);
}
///
/// Returns true if the object has a member named name, false if the member does not exist.
///
public bool ContainsMember(object obj, string name) {
return _ops.ContainsMember(obj, name);
}
///
/// Removes the member name from the object obj. Returns true if the member was successfully removed
/// or false if the member does not exist.
///
public bool RemoveMember(object obj, string name) {
return _ops.RemoveMember(obj, name);
}
///
/// Sets the member name on object obj to value.
///
public void SetMember(object obj, string name, object value) {
_ops.SetMember(obj, name, value);
}
///
/// Sets the member name on object obj to value. This overload can be used to avoid
/// boxing and casting of strongly typed members.
///
public void SetMember(object obj, string name, T value) {
_ops.SetMember(obj, name, value);
}
///
/// Gets the member name from the object obj. Throws an exception if the member does not exist or is write-only.
///
public object GetMember(object obj, string name, bool ignoreCase) {
return _ops.GetMember(obj, name, ignoreCase);
}
///
/// Gets the member name from the object obj and converts it to the type T. Throws an exception if the
/// member does not exist, is write-only, or cannot be converted.
///
public T GetMember(object obj, string name, bool ignoreCase) {
return _ops.GetMember(obj, name, ignoreCase);
}
///
/// Gets the member name from the object obj. Returns true if the member is successfully retrieved and
/// stores the value in the value out param.
///
public bool TryGetMember(object obj, string name, bool ignoreCase, out object value) {
return _ops.TryGetMember(obj, name, ignoreCase, out value);
}
///
/// Returns true if the object has a member named name, false if the member does not exist.
///
public bool ContainsMember(object obj, string name, bool ignoreCase) {
return _ops.ContainsMember(obj, name, ignoreCase);
}
///
/// Removes the member name from the object obj. Returns true if the member was successfully removed
/// or false if the member does not exist.
///
public bool RemoveMember(object obj, string name, bool ignoreCase) {
return _ops.RemoveMember(obj, name, ignoreCase);
}
///
/// Sets the member name on object obj to value.
///
public void SetMember(object obj, string name, object value, bool ignoreCase) {
_ops.SetMember(obj, name, value, ignoreCase);
}
///
/// Sets the member name on object obj to value. This overload can be used to avoid
/// boxing and casting of strongly typed members.
///
public void SetMember(object obj, string name, T value, bool ignoreCase) {
_ops.SetMember(obj, name, value, ignoreCase);
}
///
/// Convers the object obj to the type T.
///
public T ConvertTo(object obj) {
return _ops.ConvertTo(obj);
}
///
/// Converts the object obj to the type type.
///
public object ConvertTo(object obj, Type type) {
ContractUtils.RequiresNotNull(type, "type");
return _ops.ConvertTo(obj, type);
}
///
/// Converts the object obj to the type T. Returns true if the value can be converted, false if it cannot.
///
public bool TryConvertTo(object obj, out T result) {
return _ops.TryConvertTo(obj, out result);
}
///
/// Converts the object obj to the type type. Returns true if the value can be converted, false if it cannot.
///
public bool TryConvertTo(object obj, Type type, out object result) {
return _ops.TryConvertTo(obj, type, out result);
}
///
/// Converts the object obj to the type T including explicit conversions which may lose information.
///
public T ExplicitConvertTo(object obj) {
return _ops.ExplicitConvertTo(obj);
}
///
/// Converts the object obj to the type type including explicit conversions which may lose information.
///
public object ExplicitConvertTo(object obj, Type type) {
ContractUtils.RequiresNotNull(type, "type");
return _ops.ExplicitConvertTo(obj, type);
}
///
/// Converts the object obj to the type T including explicit conversions which may lose information.
///
/// Returns true if the value can be converted, false if it cannot.
///
public bool TryExplicitConvertTo(object obj, out T result) {
return _ops.TryExplicitConvertTo(obj, out result);
}
///
/// Converts the object obj to the type type including explicit conversions which may lose information.
///
/// Returns true if the value can be converted, false if it cannot.
///
public bool TryExplicitConvertTo(object obj, Type type, out object result) {
return _ops.TryExplicitConvertTo(obj, type, out result);
}
///
/// Performs a generic unary operation on the specified target and returns the result.
///
public object DoOperation(ExpressionType operation, object target) {
return _ops.DoOperation(operation, target);
}
///
/// Performs a generic unary operation on the strongly typed target and returns the value as the specified type
///
public TResult DoOperation(ExpressionType operation, TTarget target) {
return _ops.DoOperation(operation, target);
}
///
/// Performs the generic binary operation on the specified targets and returns the result.
///
public object DoOperation(ExpressionType operation, object target, object other) {
return _ops.DoOperation(operation, target, other);
}
///
/// Peforms the generic binary operation on the specified strongly typed targets and returns
/// the strongly typed result.
///
public TResult DoOperation(ExpressionType operation, TTarget target, TOther other) {
return _ops.DoOperation(operation, target, other);
}
///
/// Performs a generic unary operation on the specified target and returns the result.
///
public object DoOperation(Operators op, object target) {
return _ops.DoOperation(StandardOperators.FromOperator(op), target);
}
///
/// Performs a generic unary operation on the strongly typed target and returns the value as the specified type
///
public TResult DoOperation(Operators op, TTarget target) {
return _ops.DoOperation(StandardOperators.FromOperator(op), target);
}
///
/// Performs the generic binary operation on the specified targets and returns the result.
///
public object DoOperation(Operators op, object target, object other) {
return _ops.DoOperation(op, target, other);
}
///
/// Peforms the generic binary operation on the specified strongly typed targets and returns
/// the strongly typed result.
///
public TResult DoOperation(Operators op, TTarget target, TOther other) {
return _ops.DoOperation(StandardOperators.FromOperator(op), target, other);
}
///
/// Performs addition on the specified targets and returns the result. Throws an exception
/// if the operation cannot be performed.
///
public object Add(object self, object other) {
return _ops.DoOperation(Operators.Add, self, other);
}
///
/// Performs subtraction on the specified targets and returns the result. Throws an exception
/// if the operation cannot be performed.
///
public object Subtract(object self, object other) {
return _ops.DoOperation(Operators.Subtract, self, other);
}
///
/// Raises the first object to the power of the second object. Throws an exception
/// if the operation cannot be performed.
///
public object Power(object self, object other) {
return _ops.DoOperation(Operators.Power, self, other);
}
///
/// Multiplies the two objects. Throws an exception
/// if the operation cannot be performed.
///
public object Multiply(object self, object other) {
return _ops.DoOperation(Operators.Multiply, self, other);
}
///
/// Divides the first object by the second object. Throws an exception
/// if the operation cannot be performed.
///
public object Divide(object self, object other) {
return _ops.DoOperation(Operators.Divide, self, other);
}
///
/// Performs modulus of the 1st object by the second object. Throws an exception
/// if the operation cannot be performed.
///
public object Modulus(object self, object other) {
return _ops.DoOperation(Operators.Mod, self, other);
}
///
/// Shifts the left object left by the right object. Throws an exception if the
/// operation cannot be performed.
///
public object LeftShift(object self, object other) {
return _ops.DoOperation(Operators.LeftShift, self, other);
}
///
/// Shifts the left object right by the right object. Throws an exception if the
/// operation cannot be performed.
///
public object RightShift(object self, object other) {
return _ops.DoOperation(Operators.RightShift, self, other);
}
///
/// Performs a bitwise-and of the two operands. Throws an exception if the operation
/// cannot be performed.
///
public object BitwiseAnd(object self, object other) {
return _ops.DoOperation(Operators.BitwiseAnd, self, other);
}
///
/// Performs a bitwise-or of the two operands. Throws an exception if the operation
/// cannot be performed.
///
public object BitwiseOr(object self, object other) {
return _ops.DoOperation(Operators.BitwiseOr, self, other);
}
///
/// Performs a exclusive-or of the two operands. Throws an exception if the operation
/// cannot be performed.
///
public object ExclusiveOr(object self, object other) {
return _ops.DoOperation(Operators.ExclusiveOr, self, other);
}
///
/// Compares the two objects and returns true if the left object is less than the right object.
/// Throws an exception if hte comparison cannot be performed.
///
public bool LessThan(object self, object other) {
return _ops.DoOperation(StandardOperators.LessThan, self, other);
}
///
/// Compares the two objects and returns true if the left object is greater than the right object.
/// Throws an exception if hte comparison cannot be performed.
///
public bool GreaterThan(object self, object other) {
return _ops.DoOperation(StandardOperators.GreaterThan, self, other);
}
///
/// Compares the two objects and returns true if the left object is less than or equal to the right object.
/// Throws an exception if hte comparison cannot be performed.
///
public bool LessThanOrEqual(object self, object other) {
return _ops.DoOperation(StandardOperators.LessThanOrEqual, self, other);
}
///
/// Compares the two objects and returns true if the left object is greater than or equal to the right object.
/// Throws an exception if hte comparison cannot be performed.
///
public bool GreaterThanOrEqual(object self, object other) {
return _ops.DoOperation(StandardOperators.GreaterThanOrEqual, self, other);
}
///
/// Compares the two objects and returns true if the left object is equal to the right object.
/// Throws an exception if the comparison cannot be performed.
///
public bool Equal(object self, object other) {
return _ops.DoOperation(StandardOperators.Equal, self, other);
}
///
/// Compares the two objects and returns true if the left object is not equal to the right object.
/// Throws an exception if hte comparison cannot be performed.
///
public bool NotEqual(object self, object other) {
return _ops.DoOperation(StandardOperators.NotEqual, self, other);
}
///
/// Returns a string which describes the object as it appears in source code
///
public string GetCodeRepresentation(object obj) {
return obj.ToString();
//return _ops.DoOperation(StandardOperators.CodeRepresentation, obj);
}
///
/// Returns a list of strings which contain the known members of the object.
///
public IList OldGetMemberNames(object obj) {
return _ops.DoOperation>(StandardOperators.MemberNames, obj);
}
///
/// Returns a list of strings which contain the known members of the object.
///
public IList GetMemberNames(object obj) {
return _ops.GetMemberNames(obj);
}
///
/// Returns a string providing documentation for the specified object.
///
public string GetDocumentation(object obj) {
return _ops.DoOperation(StandardOperators.Documentation, obj);
}
///
/// Returns a list of signatures applicable for calling the specified object in a form displayable to the user.
///
public IList GetCallSignatures(object obj) {
return _ops.DoOperation>(StandardOperators.CallSignatures, obj);
}
#endregion
#pragma warning restore 618
#region Remote APIs
#if !SILVERLIGHT
// ObjectHandle overloads
//
///
/// Returns true if the remote object is callable.
///
public bool IsCallable(ObjectHandle obj) {
return IsCallable(GetLocalObject(obj));
}
///
/// Calls the specified remote object with the specified remote parameters.
///
/// Though delegates are preferable for calls they may not always be usable for remote objects.
///
public ObjectHandle Call(ObjectHandle obj, params ObjectHandle[] parameters) {
ContractUtils.RequiresNotNull(parameters, "parameters");
return new ObjectHandle(Call(GetLocalObject(obj), GetLocalObjects(parameters)));
}
///
/// Calls the specified remote object with the local parameters which will be serialized
/// to the remote app domain.
///
public ObjectHandle Call(ObjectHandle obj, params object[] parameters) {
return new ObjectHandle(Call(GetLocalObject(obj), parameters));
}
public ObjectHandle Create(ObjectHandle obj, params ObjectHandle[] parameters) {
return new ObjectHandle(CreateInstance(GetLocalObject(obj), GetLocalObjects(parameters)));
}
public ObjectHandle Create(ObjectHandle obj, params object[] parameters) {
return new ObjectHandle(CreateInstance(GetLocalObject(obj), parameters));
}
///
/// Sets the remote object as a member on the provided remote object.
///
public void SetMember(ObjectHandle obj, string name, ObjectHandle value) {
SetMember(GetLocalObject(obj), name, GetLocalObject(value));
}
///
/// Sets the member name on the remote object obj to value. This overload can be used to avoid
/// boxing and casting of strongly typed members.
///
public void SetMember(ObjectHandle obj, string name, T value) {
SetMember(GetLocalObject(obj), name, value);
}
///
/// Gets the member name on the remote object. Throws an exception if the member is not defined or
/// is write-only.
///
public ObjectHandle GetMember(ObjectHandle obj, string name) {
return new ObjectHandle(GetMember(GetLocalObject(obj), name));
}
///
/// Gets the member name on the remote object. Throws an exception if the member is not defined or
/// is write-only.
///
public T GetMember(ObjectHandle obj, string name) {
return GetMember(GetLocalObject(obj), name);
}
///
/// Gets the member name on the remote object. Returns false if the member is not defined or
/// is write-only.
///
public bool TryGetMember(ObjectHandle obj, string name, out ObjectHandle value) {
object val;
if (TryGetMember(GetLocalObject(obj), name, out val)) {
value = new ObjectHandle(val);
return true;
}
value = null;
return false;
}
///
/// Tests to see if the member name is defined on the remote object.
///
public bool ContainsMember(ObjectHandle obj, string name) {
return ContainsMember(GetLocalObject(obj), name);
}
///
/// Removes the member from the remote object
///
public bool RemoveMember(ObjectHandle obj, string name) {
return RemoveMember(GetLocalObject(obj), name);
}
///
/// Converts the remote object into the specified type returning a handle to
/// the new remote object.
///
public ObjectHandle ConvertTo(ObjectHandle obj) {
return new ObjectHandle(ConvertTo(GetLocalObject(obj)));
}
///
/// Converts the remote object into the specified type returning a handle to
/// the new remote object.
///
public ObjectHandle ConvertTo(ObjectHandle obj, Type type) {
return new ObjectHandle(ConvertTo(GetLocalObject(obj), type));
}
///
/// Converts the remote object into the specified type returning a handle to
/// the new remote object. Returns true if the value can be converted,
/// false if it cannot.
///
public bool TryConvertTo(ObjectHandle obj, out ObjectHandle result) {
T resultObj;
if (TryConvertTo(GetLocalObject(obj), out resultObj)) {
result = new ObjectHandle(resultObj);
return true;
}
result = null;
return false;
}
///
/// Converts the remote object into the specified type returning a handle to
/// the new remote object. Returns true if the value can be converted,
/// false if it cannot.
///
public bool TryConvertTo(ObjectHandle obj, Type type, out ObjectHandle result) {
object resultObj;
if (TryConvertTo(GetLocalObject(obj), type, out resultObj)) {
result = new ObjectHandle(resultObj);
return true;
}
result = null;
return false;
}
///
/// Converts the object obj to the type T including explicit conversions which may lose information.
///
public ObjectHandle ExplicitConvertTo(ObjectHandle obj) {
return new ObjectHandle(_ops.ExplicitConvertTo(GetLocalObject(obj)));
}
///
/// Converts the object obj to the type type including explicit conversions which may lose information.
///
public ObjectHandle ExplicitConvertTo(ObjectHandle obj, Type type) {
ContractUtils.RequiresNotNull(type, "type");
return new ObjectHandle(_ops.ExplicitConvertTo(GetLocalObject(obj), type));
}
///
/// Converts the object obj to the type T including explicit conversions which may lose information.
///
/// Returns true if the value can be converted, false if it cannot.
///
public bool TryExplicitConvertTo(ObjectHandle obj, out ObjectHandle result) {
T outp;
bool res = _ops.TryExplicitConvertTo(GetLocalObject(obj), out outp);
if (res) {
result = new ObjectHandle(obj);
} else {
result = null;
}
return res;
}
///
/// Converts the object obj to the type type including explicit conversions which may lose information.
///
/// Returns true if the value can be converted, false if it cannot.
///
public bool TryExplicitConvertTo(ObjectHandle obj, Type type, out ObjectHandle result) {
object outp;
bool res = _ops.TryExplicitConvertTo(GetLocalObject(obj), type, out outp);
if (res) {
result = new ObjectHandle(obj);
} else {
result = null;
}
return res;
}
///
/// Unwraps the remote object and converts it into the specified type before
/// returning it.
///
public T Unwrap(ObjectHandle obj) {
return ConvertTo(GetLocalObject(obj));
}
///
/// Performs the specified unary operator on the remote object.
///
public object DoOperation(Operators op, ObjectHandle target) {
return DoOperation(op, GetLocalObject(target));
}
///
/// Performs the specified binary operator on the remote object.
///
public ObjectHandle DoOperation(Operators op, ObjectHandle target, ObjectHandle other) {
return new ObjectHandle(DoOperation(op, GetLocalObject(target), GetLocalObject(other)));
}
///
/// Adds the two remote objects. Throws an exception if the operation cannot be performed.
///
public ObjectHandle Add(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(Add(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Subtracts the 1st remote object from the second. Throws an exception if the operation cannot be performed.
///
public ObjectHandle Subtract(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(Subtract(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Raises the 1st remote object to the power of the 2nd. Throws an exception if the operation cannot be performed.
///
public ObjectHandle Power(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(Power(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Multiplies the two remote objects. Throws an exception if the operation cannot be performed.
///
public ObjectHandle Multiply(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(Multiply(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Divides the 1st remote object by the 2nd. Throws an exception if the operation cannot be performed.
///
public ObjectHandle Divide(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(Divide(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Performs modulus on the 1st remote object by the 2nd. Throws an exception if the operation cannot be performed.
///
public ObjectHandle Modulus(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(Modulus(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Shifts the 1st remote object left by the 2nd remote object. Throws an exception if the operation cannot be performed.
///
public ObjectHandle LeftShift(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(LeftShift(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Shifts the 1st remote object right by the 2nd remote object. Throws an exception if the operation cannot be performed.
///
public ObjectHandle RightShift(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(RightShift(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Performs bitwise-and on the two remote objects. Throws an exception if the operation cannot be performed.
///
public ObjectHandle BitwiseAnd(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(BitwiseAnd(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Performs bitwise-or on the two remote objects. Throws an exception if the operation cannot be performed.
///
public ObjectHandle BitwiseOr(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(BitwiseOr(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Performs exclusive-or on the two remote objects. Throws an exception if the operation cannot be performed.
///
public ObjectHandle ExclusiveOr(ObjectHandle self, ObjectHandle other) {
return new ObjectHandle(ExclusiveOr(GetLocalObject(self), GetLocalObject(other)));
}
///
/// Compares the two remote objects and returns true if the 1st is less than the 2nd. Throws an exception if the operation cannot be performed.
///
public bool LessThan(ObjectHandle self, ObjectHandle other) {
return LessThan(GetLocalObject(self), GetLocalObject(other));
}
///
/// Compares the two remote objects and returns true if the 1st is greater than the 2nd. Throws an exception if the operation cannot be performed.
///
public bool GreaterThan(ObjectHandle self, ObjectHandle other) {
return GreaterThan(GetLocalObject(self), GetLocalObject(other));
}
///
/// Compares the two remote objects and returns true if the 1st is less than or equal to the 2nd. Throws an exception if the operation cannot be performed.
///
public bool LessThanOrEqual(ObjectHandle self, ObjectHandle other) {
return LessThanOrEqual(GetLocalObject(self), GetLocalObject(other));
}
///
/// Compares the two remote objects and returns true if the 1st is greater than or equal to than the 2nd. Throws an exception if the operation cannot be performed.
///
public bool GreaterThanOrEqual(ObjectHandle self, ObjectHandle other) {
return GreaterThanOrEqual(GetLocalObject(self), GetLocalObject(other));
}
///
/// Compares the two remote objects and returns true if the 1st is equal to the 2nd. Throws an exception if the operation cannot be performed.
///
public bool Equal(ObjectHandle self, ObjectHandle other) {
return Equal(GetLocalObject(self), GetLocalObject(other));
}
///
/// Compares the two remote objects and returns true if the 1st is not equal to the 2nd. Throws an exception if the operation cannot be performed.
///
public bool NotEqual(ObjectHandle self, ObjectHandle other) {
return NotEqual(GetLocalObject(self), GetLocalObject(other));
}
///
/// Returns a string which describes the remote object as it appears in source code
///
public string GetCodeRepresentation(ObjectHandle obj) {
return GetCodeRepresentation(GetLocalObject(obj));
}
///
/// Returns a list of strings which contain the known members of the remote object.
///
public IList GetMemberNames(ObjectHandle obj) {
return OldGetMemberNames(GetLocalObject(obj));
}
///
/// Returns a string providing documentation for the specified remote object.
///
public string GetDocumentation(ObjectHandle obj) {
return GetDocumentation(GetLocalObject(obj));
}
///
/// Returns a list of signatures applicable for calling the specified object in a form displayable to the user.
///
public IList GetCallSignatures(ObjectHandle obj) {
return GetCallSignatures(GetLocalObject(obj));
}
///
/// Helper to unwrap an object - in the future maybe we should validate the current app domain.
///
private static object GetLocalObject(ObjectHandle obj) {
ContractUtils.RequiresNotNull(obj, "obj");
return obj.Unwrap();
}
///
/// Helper to unwrap multiple objects
///
private static object[] GetLocalObjects(ObjectHandle[] ohs) {
Debug.Assert(ohs != null);
object[] res = new object[ohs.Length];
for (int i = 0; i < res.Length; i++) {
res[i] = GetLocalObject(ohs[i]);
}
return res;
}
#endif
#endregion
#if !SILVERLIGHT
// TODO: Figure out what is the right lifetime
[SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.Infrastructure)]
public override object InitializeLifetimeService() {
return null;
}
#endif
}
}