/********************************************************************++
Copyright (c) Microsoft Corporation. All rights reserved.
--********************************************************************/
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.ComponentModel;
using Microsoft.PowerShell;
#if CORECLR
using System.Reflection;
#endif
namespace System.Management.Automation
{
///
/// Implements Adapter for the COM objects.
///
internal class ComAdapter : Adapter
{
private readonly ComTypeInfo _comTypeInfo;
///
/// Constructor for the ComAdapter
///
/// typeinfo for the com object we are adapting
internal ComAdapter(ComTypeInfo typeinfo)
{
Diagnostics.Assert(typeinfo != null, "Caller to verify typeinfo is not null.");
_comTypeInfo = typeinfo;
}
internal static string GetComTypeName(string clsid)
{
StringBuilder firstType = new StringBuilder("System.__ComObject");
firstType.Append("#{");
firstType.Append(clsid);
firstType.Append("}");
return firstType.ToString();
}
///
/// Returns the TypeNameHierarchy out of an object
///
/// object to get the TypeNameHierarchy from
protected override IEnumerable GetTypeNameHierarchy(object obj)
{
yield return GetComTypeName(_comTypeInfo.Clsid);
foreach (string baseType in GetDotNetTypeNameHierarchy(obj))
{
yield return baseType;
}
}
///
/// Returns null if memberName is not a member in the adapter or
/// the corresponding PSMemberInfo
///
/// object to retrieve the PSMemberInfo from
/// name of the member to be retrieved
/// The PSMemberInfo corresponding to memberName from obj
protected override T GetMember(object obj, string memberName)
{
ComProperty prop;
if (_comTypeInfo.Properties.TryGetValue(memberName, out prop))
{
if (prop.IsParameterized)
{
if (typeof(T).IsAssignableFrom(typeof(PSParameterizedProperty)))
{
return new PSParameterizedProperty(prop.Name, this, obj, prop) as T;
}
}
else if (typeof(T).IsAssignableFrom(typeof(PSProperty)))
{
return new PSProperty(prop.Name, this, obj, prop) as T;
}
}
ComMethod method;
if (typeof(T).IsAssignableFrom(typeof(PSMethod)) &&
(_comTypeInfo != null) && (_comTypeInfo.Methods.TryGetValue(memberName, out method)))
{
PSMethod mshMethod = new PSMethod(method.Name, this, obj, method);
return mshMethod as T;
}
return null;
}
///
/// Retrieves all the members available in the object.
/// The adapter implementation is encouraged to cache all properties/methods available
/// in the first call to GetMember and GetMembers so that subsequent
/// calls can use the cache.
/// In the case of the .NET adapter that would be a cache from the .NET type to
/// the public properties and fields available in that type.
/// In the case of the DirectoryEntry adapter, this could be a cache of the objectClass
/// to the properties available in it.
///
/// object to get all the member information from
/// all members in obj
protected override PSMemberInfoInternalCollection GetMembers(object obj)
{
PSMemberInfoInternalCollection collection = new PSMemberInfoInternalCollection();
bool lookingForProperties = typeof(T).IsAssignableFrom(typeof(PSProperty));
bool lookingForParameterizedProperties = typeof(T).IsAssignableFrom(typeof(PSParameterizedProperty));
if (lookingForProperties || lookingForParameterizedProperties)
{
foreach (ComProperty prop in _comTypeInfo.Properties.Values)
{
if (prop.IsParameterized)
{
if (lookingForParameterizedProperties)
{
collection.Add(new PSParameterizedProperty(prop.Name, this, obj, prop) as T);
}
}
else if (lookingForProperties)
{
collection.Add(new PSProperty(prop.Name, this, obj, prop) as T);
}
}
}
bool lookingForMethods = typeof(T).IsAssignableFrom(typeof(PSMethod));
if (lookingForMethods)
{
foreach (ComMethod method in _comTypeInfo.Methods.Values)
{
if (collection[method.Name] == null)
{
PSMethod mshmethod = new PSMethod(method.Name, this, obj, method);
collection.Add(mshmethod as T);
}
}
}
return collection;
}
///
/// Returns an array with the property attributes
///
/// property we want the attributes from
/// an array with the property attributes
protected override AttributeCollection PropertyAttributes(PSProperty property)
{
return new AttributeCollection();
}
///
/// Returns the value from a property coming from a previous call to DoGetProperty
///
/// PSProperty coming from a previous call to DoGetProperty
/// The value of the property
protected override object PropertyGet(PSProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.GetValue(property.baseObject);
}
///
/// Sets the value of a property coming from a previous call to DoGetProperty
///
/// PSProperty coming from a previous call to DoGetProperty
/// value to set the property with
/// instructs the adapter to convert before setting, if the adapter supports conversion
protected override void PropertySet(PSProperty property, object setValue, bool convertIfPossible)
{
ComProperty prop = (ComProperty)property.adapterData;
prop.SetValue(property.baseObject, setValue);
}
///
/// Returns true if the property is settable
///
/// property to check
/// true if the property is settable
protected override bool PropertyIsSettable(PSProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.IsSettable;
}
///
/// Returns true if the property is gettable
///
/// property to check
/// true if the property is gettable
protected override bool PropertyIsGettable(PSProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.IsGettable;
}
///
/// Returns the name of the type corresponding to the property
///
/// PSProperty obtained in a previous DoGetProperty
/// True if the result is for display purposes only
/// the name of the type corresponding to the property
protected override string PropertyType(PSProperty property, bool forDisplay)
{
ComProperty prop = (ComProperty)property.adapterData;
return forDisplay ? ToStringCodeMethods.Type(prop.Type) : prop.Type.FullName;
}
///
/// get the property signature.
///
/// property object whose signature we want
/// string representing the signature of the property
protected override string PropertyToString(PSProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.ToString();
}
#region Methods
///
/// Called after a non null return from GetMethodData to try to call
/// the method with the arguments
///
/// the non empty return from GetMethods
/// the arguments to use
/// the return value for the method
protected override object MethodInvoke(PSMethod method, object[] arguments)
{
ComMethod commethod = (ComMethod)method.adapterData;
return commethod.InvokeMethod(method, arguments);
}
///
/// Called after a non null return from GetMethodData to return the overloads
///
/// the return of GetMethodData
///
protected override Collection MethodDefinitions(PSMethod method)
{
ComMethod commethod = (ComMethod)method.adapterData;
return commethod.MethodDefinitions();
}
#endregion
#region parameterized property
///
/// Returns the name of the type corresponding to the property's value
///
/// property obtained in a previous GetMember
/// the name of the type corresponding to the member
protected override string ParameterizedPropertyType(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.Type.FullName;
}
///
/// Returns true if the property is settable
///
/// property to check
/// true if the property is settable
protected override bool ParameterizedPropertyIsSettable(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.IsSettable;
}
///
/// Returns true if the property is gettable
///
/// property to check
/// true if the property is gettable
protected override bool ParameterizedPropertyIsGettable(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.IsGettable;
}
///
/// Called after a non null return from GetMember to get the property value
///
/// the non empty return from GetMember
/// the arguments to use
/// the return value for the property
protected override object ParameterizedPropertyGet(PSParameterizedProperty property, object[] arguments)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.GetValue(property.baseObject, arguments);
}
///
/// Called after a non null return from GetMember to set the property value
///
/// the non empty return from GetMember
/// the value to set property with
/// the arguments to use
protected override void ParameterizedPropertySet(PSParameterizedProperty property, object setValue, object[] arguments)
{
ComProperty prop = (ComProperty)property.adapterData;
prop.SetValue(property.baseObject, setValue, arguments);
}
///
/// Returns the string representation of the property in the object
///
/// property obtained in a previous GetMember
/// the string representation of the property in the object
protected override string ParameterizedPropertyToString(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
return prop.ToString();
}
///
/// Called after a non null return from GetMember to return the overloads
///
/// the return of GetMember
protected override Collection ParameterizedPropertyDefinitions(PSParameterizedProperty property)
{
ComProperty prop = (ComProperty)property.adapterData;
Collection returnValue = new Collection { prop.GetDefinition() };
return returnValue;
}
#endregion parameterized property
}
}