Example #1
0
		public override MethodBase SelectMethod(
			BindingFlags        bindingAttr,
			MethodBase[]        matchMethods,
			Type[]              parameterTypes,
			ParameterModifier[] modifiers)
		{
			for (int i = 0; i < matchMethods.Length; ++i)
			{
				if (matchMethods[i].IsGenericMethodDefinition != _genericMethodDefinition)
					continue;

				ParameterInfo[] pis = matchMethods[i].GetParameters();
				bool          match = (pis.Length == parameterTypes.Length);

				for (int j = 0; match && j < pis.Length; ++j)
				{
					match = TypeHelper.CompareParameterTypes(pis[j].ParameterType, parameterTypes[j]);
				}

				if (match)
					return matchMethods[i];
			}

			return null;
		}
        /// <summary> 
        ///     The only method we implement.  Our goal here is to find a method that best matches the arguments passed. 
        ///     We are doing this only with the intent of pulling attached property metadata off of the method.
        ///     If there are ambiguous methods, we simply take the first one as all "Get" methods for an attached 
        ///     property should have identical metadata.
        /// </summary>
        public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
        { 
            // Short circuit for cases where someone didn't pass in a types array.
            if (types == null) 
            { 
                if (match.Length > 1)
                { 
                    throw new AmbiguousMatchException();
                }
                else
                { 
                    return match[0];
                } 
            } 

            for(int idx = 0; idx < match.Length; idx++) 
            {
                MethodBase candidate = match[idx];
                ParameterInfo[] parameters = candidate.GetParameters();
                if (ParametersMatch(parameters, types)) 
                {
                    return candidate; 
                } 
            }
 
            return null;
        }
Example #3
0
		public override MethodBase SelectMethod(
			BindingFlags bindingAttr,
			MethodBase[] matchMethods,
			Type[] parameterTypes,
			ParameterModifier[] modifiers) {
			for (int i = 0; i < matchMethods.Length; ++i) {
				if (matchMethods[i].IsGenericMethodDefinition == _genericMethodDefinition) {
					ParameterInfo[] pis = matchMethods[i].GetParameters();

					bool match = (pis.Length == parameterTypes.Length);

					for (int j = 0; match && j < pis.Length; ++j) {
						if (pis[j].ParameterType == parameterTypes[j])
							continue;

						if (pis[j].ParameterType.IsGenericParameter)
							match = CheckGenericTypeConstraints(pis[j].ParameterType, parameterTypes[j]);
						else if (pis[j].ParameterType.IsGenericType && parameterTypes[j].IsGenericType)
							match = CompareGenericTypesRecursive(pis[j].ParameterType, parameterTypes[j]);
						else
							match = false;
					}

					if (match)
						return matchMethods[i];
				}
			}

			return null;
		}
Example #4
0
 public override MethodBase BindToMethod(
    BindingFlags bindingAttr,
    MethodBase[] match,
    ref object[] args,
    ParameterModifier[] modifiers,
    CultureInfo culture,
    string[] names,
    out object state
 )
 {
     for (int i = 0; i < args.Length; i++)
     {
         if (args[i] is string)
         {
             args[i] = ChangeType(args[i], typeof(string), culture);
         }
         if (args[i] is int)
         {
             args[i] = ChangeType(args[i], typeof(int), culture);
         }
         if (args[i] is bool)
         {
             args[i] = ChangeType(args[i], typeof(bool), culture);
         }
     }
     return Type.DefaultBinder.BindToMethod(
        bindingAttr,
        match,
        ref args,
        modifiers,
        culture,
        names,
        out state
     );
 }
 PropertyInfo IReflect.GetProperty(string name, BindingFlags bindingAttr,
     Binder binder, Type returnType, Type[] types,
     ParameterModifier[] modifiers)
 {
     return this.GetType().GetProperty(name, bindingAttr, binder,
     returnType, types, modifiers);
 }
 public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state)
 {
     object[] array = new object[args.Length];
     args.CopyTo(array, 0);
     state = null;
     try
     {
         return this.defltBinder.BindToMethod(bindingAttr, match, ref args, modifiers, culture, names, out state);
     }
     catch (MissingMethodException)
     {
         if ((match != null) && (match.Length != 0))
         {
             for (int i = 0; i < match.Length; i++)
             {
                 ParameterInfo[] parameters = match[i].GetParameters();
                 if (parameters.Length == array.Length)
                 {
                     for (int j = 0; j < parameters.Length; j++)
                     {
                         if (!parameters[j].ParameterType.IsInstanceOfType(array[j]) && (!parameters[j].ParameterType.IsArray || (array[j] != null)))
                         {
                             break;
                         }
                         if ((j + 1) == parameters.Length)
                         {
                             return match[i];
                         }
                     }
                 }
             }
         }
     }
     return null;
 }
Example #7
0
        public string GetMethod(string methodName, params IType[] args)
        {
            if (args.Any(a => a as AsmType == null))
                return null;

            var types = args.Select(t => (t as AsmType).Type).ToArray();

            MethodInfo method = null;
            if (args.Length > 0)
            {
                var modifiers = args.Select(arg => arg.Modifier == TypeModifier.Reference).ToArray();
                var mods = new ParameterModifier[] { new ParameterModifier(modifiers.Length) };
                for (var i = 0; i < modifiers.Length; i++)
                    mods[0][i] = modifiers[i];

                method = Type.GetMethod(methodName, types, mods);
            }
            else
                method = Type.GetMethod(methodName);

            if (method == null)
                return null;

            var returnType = new AsmType(method.ReturnType);
            var parameters = method.GetParameters()
                                   .Select(p => new AsmType(p.ParameterType));

            return string.Format("{0} {1}::{2}({3})",
                    returnType.Name, Name, methodName,
                    string.Join(", ", parameters.Select(p => p.Name)));
        }
Example #8
0
	// Bind a set of arguments to a method.
	public abstract MethodBase BindToMethod(BindingFlags bindingAttr,
											MethodBase[] match,
											ref Object[] args,
											ParameterModifier[] modifiers,
											CultureInfo culture,
											String[] names,
											ref Object state);
        public Command AddNamedCommand(string commandName, string text, string tooltip,
                                       ResourceBitmaps bitmapId, int status) {
            ParameterModifier pm = new ParameterModifier(7);
            for (int i = 0; i < 7; i++) {
                pm[i] = false;
            }

            // the 7th argument is a ref parameter
            pm[6] = true;

            return (Command) commandsType.InvokeMember(
                                 "AddNamedCommand2", BindingFlags.InvokeMethod, null,
                                 commands, new object[] {
                                                            Context.AddInInstance,
                                                            commandName,
                                                            text,
                                                            tooltip,
                                                            true,
                                                            59,
                                                            contextGuids
                                                            // The status parameter is not passed (yet)
                                                            // VS 2005 beta2 breaks with this parameter
                                                            // we will add it when most people have switched to final
                                                        },
                                 new ParameterModifier[] {pm}, null, null);
        }
        /// <summary>
        /// Process client request
        /// </summary>
        /// <param name="arguments">Query string parameters</param>
        /// <param name="request">Http context request</param>
        /// <returns>Number indicated http-request code (for exmpl. 200, 404, 403, 500)</returns>
        public virtual Int32 ProcessRequest(String[] arguments, System.Web.HttpRequest request)
        {
            String methodName = String.Concat("action_", arguments[0]);
            Type[] methodArgs1 = new Type[] { typeof(String[]) };
            Type[] methodArgs0 = new Type[0];
            ParameterModifier[] modifier = new ParameterModifier[0];
            BindingFlags bflags = BindingFlags.IgnoreCase | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance;

            // метод с параметром
            MethodInfo method = this.GetType().GetMethod(methodName, bflags, Type.DefaultBinder, methodArgs1, modifier)
                ?? this.GetType().GetMethod(methodName, bflags, Type.DefaultBinder, methodArgs0, modifier);

            if (method == null)
            {
                return 404;
            }

            try
            {
                return (Int32)method.Invoke(this, method.GetParameters().Length == 0 ? null : new Object[] {arguments});
            }
            catch (Exception excpn)
            {
                Logger.Error(this.GetType(), String.Format("Failed to invoke {0} method", methodName), excpn);
                return 500;
            }
        }
	public override MethodBase SelectMethod(BindingFlags bindingAttr,
											MethodBase[] match,
											Type[] types,
											ParameterModifier[] modifiers)
			{
				// TODO
				return null;
			}
 internal static MethodInfo GetMethodValidated(this Type type, string name, BindingFlags bindingAttr, Binder binder, Type[] types, ParameterModifier[] modifiers)
 {
     MethodInfo mi = type.GetMethod(name, bindingAttr, binder, types, modifiers);
     if (!mi.MatchesArgumentTypes(types))
     {
         return null;
     }
     return mi;
 }
	// Invoke a specific type member.
	public override Object InvokeMember
				(String name, BindingFlags invokeAttr, Binder binder,
				 Object target, Object[] args, ParameterModifier[] modifiers,
				 CultureInfo culture, String[] namedParameters)
			{
				return builder.InvokeMember(name, invokeAttr, binder,
										    target, args, modifiers,
										    culture, namedParameters);
			}
		internal object InvokeMember(string name, BindingFlags invokeAttr, Binder binder, object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] namedParameters)
		{
			Type type = base.GetType();
			if (!type.IsCOMObject)
			{
				throw new InvalidOperationException(Environment.GetResourceString("Arg_InvokeMember"));
			}
			return type.InvokeMember(name, invokeAttr, binder, this, args, modifiers, culture, namedParameters);
		}
Example #15
0
        protected override PropertyInfo GetPropertyImpl(string name, BindingFlags bindingAttr, Binder binder, Type returnType, Type[] types, ParameterModifier[] modifiers)
        {
            PropertyInfo info = base.GetPropertyImpl(name, bindingAttr, binder, returnType, types, modifiers);

            if (name == "ItemTemplate")
                info = new FakePropertyInfo(info, this.listViewItemType);

            return info;
        }
Example #16
0
 public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, 
   Type[] types, ParameterModifier[] modifiers)
 {
   if (match.Length == 0)
   {
     return null;
   }
   return match[0];
 }
Example #17
0
 public override PropertyInfo SelectProperty(BindingFlags bindingAttr, PropertyInfo[] match, 
   Type returnType, Type[] indexes, ParameterModifier[] modifiers)
 {
   if (match.Length == 0)
   {
     return null;
   }
   return match[0];
 }
Example #18
0
 public override MethodBase SelectMethod(
    BindingFlags bindingAttr,
    MethodBase[] match,
    Type[] types,
    ParameterModifier[] modifiers
 )
 {
     throw new NotImplementedException();
 }
		protected override ConstructorInfo GetConstructorImpl (BindingFlags bindingAttr,
								       Binder binder,
								       CallingConventions callConvention,
								       Type[] types,
								       ParameterModifier[] modifiers)
		{
			ConstructorInfo[] methods = GetConstructors (bindingAttr);
			return GetConstructorImpl (methods, bindingAttr, binder, callConvention, types, modifiers);
		}
        /// <summary>
        /// 获取指定响应 头部信息
        /// </summary>
        /// <param name="header">指定头名称</param>
        /// <returns></returns>
        public string GetResponseHeader(string header)
        {
            var parames = new System.Reflection.ParameterModifier[1];

            parames[0]    = new System.Reflection.ParameterModifier(2); // 初始化为接口参数的个数
            parames[0][1] = true;                                       // 设置第二个参数为返回参数
            var obj = this.DoMethod("GetResponseHeader", new object[] { header }, parames);

            return(obj != null?obj.ToString() : "");
        }
Example #21
0
 public override PropertyInfo SelectProperty(
    BindingFlags bindingAttr,
    PropertyInfo[] match,
    Type returnType,
    Type[] indexes,
    ParameterModifier[] modifiers
 )
 {
     throw new NotImplementedException();
 }
	public override MethodBase BindToMethod(BindingFlags bindingAttr,
											MethodBase[] match,
											ref Object[] args,
											ParameterModifier[] modifiers,
											CultureInfo culture,
											String[] names,
											ref Object state)
			{
				// TODO
				return null;
			}
Example #23
0
        // Returns the matching method if the parameter types are reference
        // assignable from the provided type arguments, otherwise null. 
        internal static MethodInfo GetMethodValidated(
            this Type type,
            string name,
            BindingFlags bindingAttr,
            Binder binder,
            Type[] types,
            ParameterModifier[] modifiers) {
            
            var method = type.GetMethod(name, bindingAttr, binder, types, modifiers);

            return method.MatchesArgumentTypes(types) ? method : null;
        }
Example #24
0
        // for remote COM Objects the late binding methods can't be
        // executed on proxies, so we need this method to execute on
        // the real object
        internal Object InvokeMember(String name,BindingFlags invokeAttr,Binder binder, 
                            Object[] args,ParameterModifier[] modifiers,CultureInfo culture,String[] namedParameters)
        {
            Type t = GetType();
            
            // Sanity check
            if(!t.IsCOMObject)
                throw new InvalidOperationException(Environment.GetResourceString("Arg_InvokeMember"));

            // Call into the runtime to invoke on the COM object.
            return t.InvokeMember(name, invokeAttr, binder, this, args, modifiers, culture, namedParameters);
        }
Example #25
0
        public override MethodBase SelectMethod(BindingFlags bindingAttr, MethodBase[] match, Type[] types, ParameterModifier[] modifiers)
        {
            MethodBase matchingMethod = Type.DefaultBinder.SelectMethod(bindingAttr, match, types, modifiers);

            if (matchingMethod != null)
                return matchingMethod;

            foreach (MethodBase method in match)
                if (ParametersMatch(types, method.GetParameters()))
                    return method;

            return null;
        }
Example #26
0
 public MethodInfo GetMethod(string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers)
 {
     if (name == null)
         throw new ArgumentNullException(nameof(name));
     if (types == null)
         throw new ArgumentNullException(nameof(types));
     for (int i = 0; i < types.Length; i++)
     {
         if (types[i] == null)
             throw new ArgumentNullException(nameof(types));
     }
     return GetMethodImpl(name, bindingAttr, binder, callConvention, types, modifiers);
 }
Example #27
0
 public override MethodBase BindToMethod(
     BindingFlags bindingAttr,
     MethodBase[] match,
     ref object[] args,
     ParameterModifier[] modifiers,
     CultureInfo culture,
     string[] names,
     out object state
     )
 {
     // Store the arguments to the method in a state object.
     BinderState myBinderState = new BinderState();
     object[] arguments = new Object[args.Length];
     args.CopyTo(arguments, 0);
     myBinderState.args = arguments;
     state = myBinderState;
     if (match == null)
         throw new ArgumentNullException();
     // Find a method that has the same parameters as those of the args parameter.
     for (int i = 0; i < match.Length; i++)
     {
         // Count the number of parameters that match.
         int count = 0;
         ParameterInfo[] parameters = match[i].GetParameters();
         // Go on to the next method if the number of parameters do not match.
         if (args.Length != parameters.Length)
             continue;
         // Match each of the parameters that the user expects the method to have.
         for (int j = 0; j < args.Length; j++)
         {
             // If the names parameter is not null, then reorder args.
             if (names != null)
             {
                 if (names.Length != args.Length)
                     throw new ArgumentException("names and args must have the same number of elements.");
                 for (int k = 0; k < names.Length; k++)
                     if (String.Compare(parameters[j].Name, names[k].ToString()) == 0)
                         args[j] = myBinderState.args[k];
             }
             // Determine whether the types specified by the user can be converted to the parameter type.
             if (ChangeType(args[j], parameters[j].ParameterType, culture) != null)
                 count += 1;
             else
                 break;
         }
         // Determine whether the method has been found.
         if (count == args.Length)
             return match[i];
     }
     return null;
 }
 public static void Deploy(SPSolution solution, Collection<SPWebApplication> applications, int minCompat, int maxCompat, ILog log)
 {
     #if SP2013
     SPSolutionLanguagePack languagePack = solution.GetLanguagePack(0);
     SPCompatibilityRange compatibilityRange = new SPCompatibilityRange(minCompat, maxCompat);
     Type deployType = languagePack.GetType();
     Type[] argumentTypes = new Type[] { typeof(DateTime), applications.GetType(), typeof(SPSolutionDeploymentJobType), typeof(bool), typeof(bool), typeof(bool), compatibilityRange.GetType() };
     ParameterModifier[] modifiers = new ParameterModifier[] { new ParameterModifier(7) };
     MethodInfo deployMethod = deployType.GetMethod("CreateSolutionDeployTimerJob", BindingFlags.Instance | BindingFlags.NonPublic, null, argumentTypes, modifiers);
     DateTime jobTime = GetImmediateJobTime();
     object[] args = new object[] { jobTime, applications, SPSolutionDeploymentJobType.Deploy, true, true, false, compatibilityRange };
     deployMethod.Invoke(languagePack, args);
     #endif
 }
        public void GetFullMatrix(string name, string workspace, ref Array reals, ref Array imaginary)
        {
            Array a1 = new double[reals.Length];
            Array a2 = new double[imaginary.Length];
            object[] args = {name, workspace, a1, a2};
            var p = new ParameterModifier(4);
            p[0] = false;
            p[1] = false;
            p[2] = true;
            p[3] = true;
            ParameterModifier[] mods = {p};

            type.InvokeMember("GetFullMatrix", BindingFlags.InvokeMethod, null, instance, args, mods, null, null);

            reals = (Array)args[2];
        }
Example #30
0
        public override MethodBase BindToMethod(
           BindingFlags bindingAttr,
           MethodBase[] match,
           ref object[] args,
           ParameterModifier[] modifiers,
           CultureInfo culture,
           string[] names,
           out object state
        )
        {
            try
            {
                for (int i = 0; i < args.Length; i++)
                {
                    if (args[i] is string)
                    {
                        args[i] = ChangeType(args[i], typeof(string), culture);
                    }
                    if (args[i] is int)
                    {
                        args[i] = ChangeType(args[i], typeof(int), culture);
                    }
                    if (args[i] is bool)
                    {
                        args[i] = ChangeType(args[i], typeof(bool), culture);
                    }
                }
                return Type.DefaultBinder.BindToMethod(
                   bindingAttr,
                   match,
                   ref args,
                   modifiers,
                   culture,
                   names,
                   out state
                );
            }
            catch (Exception ex)
            {
                ex.Data.Add("My Key", "--Current_Exit()---VMukti--:--VmuktiModules--:--Collaborative--:--Video.Presentation--:--DomainBinder.cs--:");
                ClsException.LogError(ex);
                ClsException.WriteToErrorLogFile(ex);

                state = null;
                return null;
            }
        }
		/// <summary>
		/// Returns closest method (if not found in specified <paramref name="type"/>, search base interfaces).
		/// </summary>
		/// <remarks>Delegates work to <see cref="Type.GetMethod(string, BindingFlags, Binder, Type[], ParameterModifier[])"/>.</remarks>
		/// <exception cref="ArgumentOutOfRangeException">If method with specified name does not found.</exception>
		public static MethodInfo GetMethod(Type type, string name, BindingFlags bindingAttr, 
			Type[] parameterTypes, Binder binder = null, ParameterModifier[] modifiers = null)
		{
			if (type == null) throw new ArgumentNullException("type");
			var result = type.GetMethod(name, bindingAttr, binder, parameterTypes, modifiers);
			if (result != null)
				return result;

			foreach (var baseInterface in type.GetInterfaces())
			{
				result = baseInterface.GetMethod(name, bindingAttr, binder, parameterTypes, modifiers);
				if (result != null)
					return result;
			}
			
			throw new ArgumentOutOfRangeException("name");
		}
        /// <summary>
        /// 等待数据提交完成 等待异步发送完成(以秒为单位)
        /// </summary>
        /// <param name="timeout"></param>
        /// <param name="succeeded"></param>
        /// <returns></returns>
        public string WaitForResponse(object timeout, out bool succeeded)
        {
            const bool succ     = false;
            var        paramesM = new System.Reflection.ParameterModifier[1];

            paramesM[0]    = new System.Reflection.ParameterModifier(2); // 初始化为接口参数的个数
            paramesM[0][1] = true;                                       // 设置第二个参数为返回参数

            //ParamesM[1] = true;
            var paramArray = new object[2] {
                timeout, succ
            };
            var obj = this.DoMethod("WaitForResponse", paramArray, paramesM);

            System.Windows.Forms.MessageBox.Show(paramArray[1].ToString());
            succeeded = bool.Parse(paramArray[1].ToString());
            //Succeeded = bool.Parse(ParamArray[1].ToString);
            return(obj != null?obj.ToString() : "");
        }
Example #33
0
        public void ParamByRef()
        {
            var c = new CodeDomGenerator();

            c.AddNamespace("Samples").AddClass("cls")
            .AddMethod(MemberAttributes.Static | MemberAttributes.Public,
                       (RefParam <int> i, DynTypeRef j) => "foo" + j.SetType(typeof(string)),
                       Emit.assignVar("i", () => 10),
                       Emit.assignVar("j", () => "zzz")
                       )
            ;

            Console.WriteLine(c.GenerateCode(CodeDomGenerator.Language.CSharp));

            Console.WriteLine(c.GenerateCode(CodeDomGenerator.Language.VB));

            var ass = c.Compile();

            Assert.IsNotNull(ass);

            Type cls = ass.GetType("Samples.cls");

            Assert.IsNotNull(cls);

            object[] args = new object[] { 0, "" };
            System.Reflection.ParameterModifier p = new System.Reflection.ParameterModifier(2);
            p[0] = true;
            p[1] = true;

            string s = (string)cls.InvokeMember("foo",
                                                System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.InvokeMethod | System.Reflection.BindingFlags.Static,
                                                null, new System.Reflection.ParameterModifier[] { p }, args);

            Assert.AreEqual(10, args[0]);
            Assert.AreEqual("zzz", args[1]);
        }
Example #34
0
            public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, CultureInfo culture, string[] names, out object state)
            {
                Type[] types;
                if (args == null)
                {
                    types = Type.EmptyTypes;
                }
                else
                {
                    types = new Type [args.Length];
                    for (int i = 0; i < args.Length; ++i)
                    {
                        if (args [i] != null)
                        {
                            types [i] = args [i].GetType();
                        }
                    }
                }

                MethodBase selected = null;

                if (names != null)
                {
                    foreach (var m in match)
                    {
                        var parameters = m.GetParametersInternal();
                        int i;

                        /*
                         * Find the corresponding parameter for each parameter name,
                         * reorder types/modifiers array during the search.
                         */
                        Type[] newTypes = new Type [types.Length];
                        Array.FastCopy(types, 0, newTypes, 0, types.Length);

                        ParameterModifier[] newModifiers = null;
                        if (modifiers != null)
                        {
                            newModifiers = new ParameterModifier [modifiers.Length];
                            Array.FastCopy(modifiers, 0, newModifiers, 0, modifiers.Length);
                        }

                        for (i = 0; i < names.Length; ++i)
                        {
                            /* Find the corresponding parameter */
                            int nindex = -1;
                            for (int j = 0; j < parameters.Length; ++j)
                            {
                                if (parameters [j].Name == names [i])
                                {
                                    nindex = j;
                                    break;
                                }
                            }
                            if (nindex == -1)
                            {
                                break;
                            }
                            if (i < newTypes.Length && nindex < types.Length)
                            {
                                newTypes [i] = types [nindex];
                            }
                            if (modifiers != null && i < newModifiers.Length && nindex < modifiers.Length)
                            {
                                newModifiers [i] = modifiers [nindex];
                            }
                        }
                        if (i < names.Length)
                        {
                            continue;
                        }

                        selected = SelectMethod(bindingAttr, new MethodBase [] { m }, newTypes, newModifiers, true, ref args);
                        if (selected != null)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    selected = SelectMethod(bindingAttr, match, types, modifiers, true, ref args);
                }

                state = null;
                if (selected != null && names != null)
                {
                    ReorderParameters(names, ref args, selected);
                }

                if (selected != null)
                {
                    if (args == null)
                    {
                        args = EmptyArray <object> .Value;
                    }

                    AdjustArguments(selected, ref args);
                }

                return(selected);
            }