e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
285 lines
10 KiB
C#
285 lines
10 KiB
C#
//------------------------------------------------------------
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//------------------------------------------------------------
|
|
|
|
namespace System.ServiceModel.Description
|
|
{
|
|
using System.Collections.Generic;
|
|
using System.ServiceModel;
|
|
using System.ServiceModel.Activation;
|
|
using System.Collections.ObjectModel;
|
|
using System.Runtime;
|
|
using System.Runtime.Serialization;
|
|
using System.Reflection;
|
|
using System.Diagnostics;
|
|
using System.Security;
|
|
using System.Security.Permissions;
|
|
|
|
[DebuggerDisplay("ServiceType={serviceType}")]
|
|
public class ServiceDescription
|
|
{
|
|
KeyedByTypeCollection<IServiceBehavior> behaviors = new KeyedByTypeCollection<IServiceBehavior>();
|
|
string configurationName;
|
|
ServiceEndpointCollection endpoints = new ServiceEndpointCollection();
|
|
Type serviceType;
|
|
XmlName serviceName;
|
|
string serviceNamespace = NamingHelper.DefaultNamespace;
|
|
|
|
|
|
public ServiceDescription()
|
|
{
|
|
}
|
|
|
|
internal ServiceDescription(String serviceName)
|
|
{
|
|
if (String.IsNullOrEmpty(serviceName))
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceName");
|
|
|
|
this.Name = serviceName;
|
|
}
|
|
|
|
public ServiceDescription(IEnumerable<ServiceEndpoint> endpoints)
|
|
: this()
|
|
{
|
|
if (endpoints == null)
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpoints");
|
|
|
|
foreach (ServiceEndpoint endpoint in endpoints)
|
|
this.endpoints.Add(endpoint);
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get
|
|
{
|
|
if (serviceName != null)
|
|
return serviceName.EncodedName;
|
|
else if (ServiceType != null)
|
|
return NamingHelper.XmlName(ServiceType.Name);
|
|
else
|
|
return NamingHelper.DefaultServiceName;
|
|
}
|
|
set
|
|
{
|
|
if (string.IsNullOrEmpty(value))
|
|
{
|
|
serviceName = null;
|
|
}
|
|
else
|
|
{
|
|
// the XmlName ctor validate the value
|
|
serviceName = new XmlName(value, true /*isEncoded*/);
|
|
}
|
|
}
|
|
}
|
|
|
|
public string Namespace
|
|
{
|
|
get
|
|
{
|
|
return serviceNamespace;
|
|
}
|
|
set
|
|
{
|
|
serviceNamespace = value;
|
|
}
|
|
}
|
|
|
|
|
|
public KeyedByTypeCollection<IServiceBehavior> Behaviors
|
|
{
|
|
get { return this.behaviors; }
|
|
}
|
|
|
|
public string ConfigurationName
|
|
{
|
|
get { return this.configurationName; }
|
|
set
|
|
{
|
|
if (value == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
|
|
}
|
|
this.configurationName = value;
|
|
}
|
|
}
|
|
|
|
public ServiceEndpointCollection Endpoints
|
|
{
|
|
get { return this.endpoints; }
|
|
}
|
|
|
|
public Type ServiceType
|
|
{
|
|
get { return this.serviceType; }
|
|
set { this.serviceType = value; }
|
|
}
|
|
|
|
static void AddBehaviors(ServiceDescription serviceDescription)
|
|
{
|
|
Type type = serviceDescription.ServiceType;
|
|
|
|
System.ServiceModel.Description.TypeLoader.ApplyServiceInheritance<IServiceBehavior, KeyedByTypeCollection<IServiceBehavior>>(
|
|
type, serviceDescription.Behaviors, ServiceDescription.GetIServiceBehaviorAttributes);
|
|
|
|
ServiceBehaviorAttribute serviceBehavior = EnsureBehaviorAttribute(serviceDescription);
|
|
|
|
if (serviceBehavior.Name != null)
|
|
serviceDescription.Name = new XmlName(serviceBehavior.Name).EncodedName;
|
|
if (serviceBehavior.Namespace != null)
|
|
serviceDescription.Namespace = serviceBehavior.Namespace;
|
|
|
|
if (String.IsNullOrEmpty(serviceBehavior.ConfigurationName))
|
|
{
|
|
serviceDescription.ConfigurationName = type.FullName;
|
|
}
|
|
else
|
|
{
|
|
serviceDescription.ConfigurationName = serviceBehavior.ConfigurationName;
|
|
}
|
|
|
|
AspNetEnvironment.Current.EnsureCompatibilityRequirements(serviceDescription);
|
|
}
|
|
|
|
internal static object CreateImplementation(Type serviceType)
|
|
{
|
|
ConstructorInfo constructor = serviceType.GetConstructor(
|
|
TypeLoader.DefaultBindingFlags, null, Type.EmptyTypes, null);
|
|
if (constructor == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
|
|
SR.GetString(SR.SFxNoDefaultConstructor)));
|
|
}
|
|
|
|
// Stop the partially trusted callers to use the ServiceDescription.GetService(Type) method to
|
|
// instantiate types in this assembly that are not public or have a non-public default constructor.
|
|
if ((!PartialTrustHelpers.AppDomainFullyTrusted) &&
|
|
(serviceType.IsNotPublic || (!constructor.IsPublic)) &&
|
|
(serviceType.Assembly == typeof(ServiceDescription).Assembly))
|
|
{
|
|
PartialTrustHelpers.DemandForFullTrust();
|
|
}
|
|
|
|
try
|
|
{
|
|
object implementation = constructor.Invoke(
|
|
TypeLoader.DefaultBindingFlags, null, null, System.Globalization.CultureInfo.InvariantCulture);
|
|
return implementation;
|
|
}
|
|
catch (MethodAccessException methodAccessException)
|
|
{
|
|
SecurityException securityException = methodAccessException.InnerException as SecurityException;
|
|
if (securityException != null && securityException.PermissionType.Equals(typeof(ReflectionPermission)))
|
|
{
|
|
DiagnosticUtility.TraceHandledException(methodAccessException, TraceEventType.Warning);
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
|
|
new SecurityException(SR.GetString(
|
|
SR.PartialTrustServiceCtorNotVisible,
|
|
serviceType.FullName)));
|
|
}
|
|
else
|
|
{
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
static ServiceBehaviorAttribute EnsureBehaviorAttribute(ServiceDescription description)
|
|
{
|
|
ServiceBehaviorAttribute attr = description.Behaviors.Find<ServiceBehaviorAttribute>();
|
|
|
|
if (attr == null)
|
|
{
|
|
attr = new ServiceBehaviorAttribute();
|
|
description.Behaviors.Insert(0, attr);
|
|
}
|
|
|
|
return attr;
|
|
}
|
|
|
|
// This method ensures that the description object graph is structurally sound and that none
|
|
// of the fundamental SFx framework assumptions have been violated.
|
|
internal void EnsureInvariants()
|
|
{
|
|
for (int i = 0; i < this.Endpoints.Count; i++)
|
|
{
|
|
ServiceEndpoint endpoint = this.Endpoints[i];
|
|
if (endpoint == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.AChannelServiceEndpointIsNull0)));
|
|
}
|
|
endpoint.EnsureInvariants();
|
|
}
|
|
}
|
|
|
|
static void GetIServiceBehaviorAttributes(Type currentServiceType, KeyedByTypeCollection<IServiceBehavior> behaviors)
|
|
{
|
|
foreach (IServiceBehavior behaviorAttribute in ServiceReflector.GetCustomAttributes(currentServiceType, typeof(IServiceBehavior)))
|
|
{
|
|
behaviors.Add(behaviorAttribute);
|
|
}
|
|
}
|
|
|
|
public static ServiceDescription GetService(Type serviceType)
|
|
{
|
|
if (serviceType == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceType");
|
|
}
|
|
|
|
if (!serviceType.IsClass)
|
|
{
|
|
throw new ArgumentException(SR.GetString(SR.SFxServiceHostNeedsClass));
|
|
}
|
|
|
|
ServiceDescription description = new ServiceDescription();
|
|
description.ServiceType = serviceType;
|
|
|
|
AddBehaviors(description);
|
|
SetupSingleton(description, null, false);
|
|
return description;
|
|
}
|
|
|
|
public static ServiceDescription GetService(object serviceImplementation)
|
|
{
|
|
if (serviceImplementation == null)
|
|
{
|
|
throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceImplementation");
|
|
}
|
|
|
|
Type serviceType = serviceImplementation.GetType();
|
|
ServiceDescription description = new ServiceDescription();
|
|
description.ServiceType = serviceType;
|
|
|
|
if (serviceImplementation is IServiceBehavior)
|
|
{
|
|
description.Behaviors.Add((IServiceBehavior)serviceImplementation);
|
|
}
|
|
|
|
AddBehaviors(description);
|
|
SetupSingleton(description, serviceImplementation, true);
|
|
return description;
|
|
}
|
|
|
|
static void SetupSingleton(ServiceDescription serviceDescription, object implementation, bool isWellKnown)
|
|
{
|
|
ServiceBehaviorAttribute serviceBehavior = EnsureBehaviorAttribute(serviceDescription);
|
|
Type type = serviceDescription.ServiceType;
|
|
if ((implementation == null) && (serviceBehavior.InstanceContextMode == InstanceContextMode.Single))
|
|
{
|
|
implementation = CreateImplementation(type);
|
|
}
|
|
|
|
if (isWellKnown)
|
|
{
|
|
serviceBehavior.SetWellKnownSingleton(implementation);
|
|
}
|
|
else if ((implementation != null) && (serviceBehavior.InstanceContextMode == InstanceContextMode.Single))
|
|
{
|
|
serviceBehavior.SetHiddenSingleton(implementation);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|