Как определить, является ли свойство определяемым пользователем типом в С#?
Как определить, является ли свойство определяемым пользователем типом? Я попытался использовать IsClass, как показано ниже, но его значение было истинным для свойств String (и кто знает, что еще).
foreach (var property in type.GetProperties()) {
if (property.PropertyType.IsClass) {
// do something with property
}
}
* Обновлено для большей ясности *
Я пытаюсь пройти определение определенного типа, и если данный тип или любые его общедоступные свойства определены в сборке, я ищу встроенный документ JavaScript. Я просто не хочу тратить ресурсы обработки и время на собственные типы .NET.
Ответы
Ответ 1
@Bobson сделал действительно хороший момент:
"... В отличие от некоторых других языков, С# не делает никаких реальных различие между" определяемыми пользователем "и" стандартными "типами."
Технически, @Bobson дал ответ; нет различительной разницы между определяемым пользователем типом и значением, определенным в .NET Framework или любой другой сборке, если на то пошло.
Однако, я нашел пару полезных способов определить, является ли тип определяемым пользователем.
Для поиска всех типов, определенных в сборке данного типа, это отлично работает:
foreach (var property in type.GetProperties()) {
if (property.PropertyType.IsClass
&& property.PropertyType.Assembly.FullName == type.Assembly.FullName) {
// do something with property
}
}
Если типы могут быть определены в разных сборках, в большинстве случаев исключается пространство имен Система:
foreach (var property in type.GetProperties()) {
if (property.PropertyType.IsClass
&& !property.PropertyType.FullName.StartsWith("System.")) {
// do something with property
}
}
Ответ 2
Если под "определяемым пользователем" вы подразумеваете, что он не является частью стандартной сборки (mscorlib), тогда вы можете сделать что-то в этом направлении:
if(typeof(SomeType).Assembly.GetName().Name != "mscorlib") {
// user-defined!
}
Однако это также рассмотрит типы внешних сборок (aka: libraries), которые будут считаться "определяемыми пользователем". Если вы хотите только те, что есть в текущей сборке, вы можете использовать
typeof(SomeType).Assembly == Assembly.GetExecutingAssembly()
Ответ 3
Я написал общий наполнитель для модульного тестирования, который назначает предсказуемые значения моим объектам и сталкивается с такой проблемой. В моем случае я хотел знать, какие из моих свойств были объектами, чтобы я мог рекурсивно заполнять эти свойства объекта, опять же с предсказуемыми значениями.
Мне показалось, что введение интерфейса, реализованного только классами, которые мне интересны в обходе, было лучшим способом сделать это. Затем вы можете проверить, является ли ваше свойство объектом интереса:
public static bool IsMyInterface(this Type propertyType)
{
return propertyType.GetInterface("MyInterfaceName") != null;
}
Ответ 4
Если по типу "определяемый пользователем" вы подразумеваете тип, объявленный в вашей исполняющей сборке, вы можете получить список таких типов, как в этом примере приложения консоли С#:
class Program
{
static void Main( string[] args )
{
var currentAssembly = Assembly.GetExecutingAssembly();
var localTypes = currentAssembly.GetTypes();
}
}
UPDATE:
Если вы хотите получить список типов из всех ссылочных ассемблеров:
class Program
{
static void Main( string[] args )
{
var currentAssembly = Assembly.GetExecutingAssembly();
var referencedAssemblies = currentAssembly.GetReferencedAssemblies();
var typesFromReferencedAssemblies = referencedAssemblies.Select( assemblyName => Assembly.ReflectionOnlyLoad( assemblyName.FullName ) ).SelectMany( assembly => assembly.GetTypes() );
}
}
Просто помните, что тип Program
также будет в этом списке. Является ли это достаточным ответом на вашу проблему?