Если вы действительно должны сделать это с помощью отражения, вы можете сделать это так:
var employees = new Employees();
var type = employees.GetType();
for (int i = 1; i <= 4; ++i)
type.GetProperty("field"+i).SetValue(employees, "abcde");
Console.WriteLine(employees.field1); // Prints "abcde"
Как указывают другие люди, использование отражения таким образом кажется немного подозрительным. Похоже, вы должны делать это по-другому, например, используя Dictionary<string,string>
.
Обновление Мой первоначальный ответ ниже был написан 6 лет назад в стиле, подходящем для времени и моего понимания. В ответ на какой-то разговор в комментариях более современный подход к этому выглядит следующим образом:
(function() {
if ( typeof Object.id == "undefined" ) {
var id = 0;
Object.id = function(o) {
if ( typeof o.__uniqueid == "undefined" ) {
Object.defineProperty(o, "__uniqueid", {
value: ++id,
enumerable: false,
// This could go either way, depending on your
// interpretation of what an "id" is
writable: false
});
}
return o.__uniqueid;
};
}
})();
var obj = { a: 1, b: 1 };
console.log(Object.id(obj));
console.log(Object.id([]));
console.log(Object.id({}));
console.log(Object.id(/./));
console.log(Object.id(function() {}));
for (var k in obj) {
if (obj.hasOwnProperty(k)) {
console.log(k);
}
}
// Logged keys are `a` and `b`
Если у вас есть требования к архаичному браузеру, проверьте здесь для совместимости браузеров для Object.defineProperty
.
Оригинальный ответ хранится ниже (а не только в истории изменений), потому что я считаю, что сравнение ценно.
Вы можете дать следующее вращение. Это также дает вам возможность явно установить идентификатор объекта в его конструкторе или в другом месте.
(function() {
if ( typeof Object.prototype.uniqueId == "undefined" ) {
var id = 0;
Object.prototype.uniqueId = function() {
if ( typeof this.__uniqueid == "undefined" ) {
this.__uniqueid = ++id;
}
return this.__uniqueid;
};
}
})();
var obj1 = {};
var obj2 = new Object();
console.log(obj1.uniqueId());
console.log(obj2.uniqueId());
console.log([].uniqueId());
console.log({}.uniqueId());
console.log(/./.uniqueId());
console.log((function() {}).uniqueId());
Позаботьтесь о том, чтобы любой член, который вы используете для внутреннего хранения уникального идентификатора, не сталкивался с другим автоматически созданный имя участника.
Последние браузеры предоставляют более чистый метод расширения Object.prototype. Этот код сделает свойство скрытым от перечисления свойств (для p in o)
. Для браузеров , реализующих defineProperty , вы можете реализовать свойство uniqueId следующим образом:
(function() {
var id_counter = 1;
Object.defineProperty(Object.prototype, "__uniqueId", {
writable: true
});
Object.defineProperty(Object.prototype, "uniqueId", {
get: function() {
if (this.__uniqueId == undefined)
this.__uniqueId = id_counter++;
return this.__uniqueId;
}
});
}());
Подробнее см. в https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty
Я использовал такой код, который заставит объекты строчить с помощью уникальных строк:
Object.prototype.__defineGetter__('__id__', function () {
var gid = 0;
return function(){
var id = gid++;
this.__proto__ = {
__proto__: this.__proto__,
get __id__(){ return id }
};
return id;
}
}.call() );
Object.prototype.toString = function () {
return '[Object ' + this.__id__ + ']';
};
биты __proto__
предназначены для того, чтобы геттер __id__
не отображался в объекте , это было проверено только в firefox.
__defineGetter__
является нестандартным.
– Tomáš Zato
29 September 2015 в 21:36
Типовая версия ответа @justin, совместимая с ES6, с использованием символов для предотвращения любого столкновения ключей и добавления в глобальный Object.id для удобства. Просто скопируйте вставить код ниже или поместите его в файл ObjecId.ts, который вы импортируете.
(enableObjectID)();
const uniqueId: symbol = Symbol('The unique id of an object');
function enableObjectID(): void {
if (typeof Object['id'] !== 'undefined') {
return;
}
let id: number = 0;
Object['id'] = (object: any) => {
const hasUniqueId: boolean = !!object[uniqueId];
if (!hasUniqueId) {
object[uniqueId] = ++id;
}
return object[uniqueId];
};
}
Использование в вашем ts-коде:
(<any>Object).id(yourObject);
Насколько мне известно, любой ответ, который может быть опубликован здесь, может иметь неожиданные побочные эффекты.
В среде, совместимой с ES2015, вы можете избежать любых побочных эффектов, используя WeakMap .
const id = (() => {
let currentId = 0;
const map = new WeakMap();
return (object) => {
if (!map.has(object)) {
map.set(object, ++currentId);
}
return map.get(object);
};
})();
id({}); //=> 1
Я столкнулся с той же проблемой, и вот решение, которое я использовал с ES6
code
let id = 0; // This is a kind of global variable accessible for every instance
class Animal {
constructor(name){
this.name = name;
this.id = id++;
}
foo(){}
// Executes some cool stuff
}
cat = new Animal("Catty");
console.log(cat.id) // 1
На самом деле вам не нужно изменять прототип object
и добавлять туда функцию. Следующее должно хорошо работать для вашей цели.
var __next_objid=1;
function objectId(obj) {
if (obj==null) return null;
if (obj.__obj_id==null) obj.__obj_id=__next_objid++;
return obj.__obj_id;
}
Несмотря на рекомендации не изменять Object.prototype, это может быть действительно полезно для тестирования в ограниченном объеме. Автор принятого ответа изменил его, но все еще устанавливает Object.id
, что для меня не имеет смысла. Вот фрагмент, который выполняет задание:
// Generates a unique, read-only id for an object.
// The _uid is generated for the object the first time it's accessed.
(function() {
var id = 0;
Object.defineProperty(Object.prototype, '_uid', {
// The prototype getter sets up a property on the instance. Because
// the new instance-prop masks this one, we know this will only ever
// be called at most once for any given object.
get: function () {
Object.defineProperty(this, '_uid', {
value: id++,
writable: false,
enumerable: false,
});
return this._uid;
},
enumerable: false,
});
})();
function assert(p) { if (!p) throw Error('Not!'); }
var obj = {};
assert(obj._uid == 0);
assert({}._uid == 1);
assert([]._uid == 2);
assert(obj._uid == 0); // still
Для браузеров, реализующих метод Object.defineProperty()
, приведенный ниже код генерирует и возвращает функцию, которую вы можете привязать к любому принадлежащему вам объекту.
Преимущество этого подхода заключается в том, что он не расширяется Object.prototype
.
Код работает, проверяя, обладает ли данный объект свойством __objectID__
, и определив его как скрытое (неперечислимое) свойство только для чтения, если оно отсутствует.
Итак, это защищен от любых попыток изменить или переопределить свойство obj.__objectID__
только для чтения, после того как оно определено, и последовательно генерирует приятную ошибку вместо молчания.
Наконец, в довольно экстремальном случае, когда некоторые другой код уже определил __objectID__
для данного объекта, это значение просто будет возвращено.
var getObjectID = (function () {
var id = 0; // Private ID counter
return function (obj) {
if(obj.hasOwnProperty("__objectID__")) {
return obj.__objectID__;
} else {
++id;
Object.defineProperty(obj, "__objectID__", {
/*
* Explicitly sets these two attribute values to false,
* although they are false by default.
*/
"configurable" : false,
"enumerable" : false,
/*
* This closure guarantees that different objects
* will not share the same id variable.
*/
"get" : (function (__objectID__) {
return function () { return __objectID__; };
})(id),
"set" : function () {
throw new Error("Sorry, but 'obj.__objectID__' is read-only!");
}
});
return obj.__objectID__;
}
};
})();
Код jQuery использует свой собственный метод data()
как такой идентификатор.
var id = $.data(object);
В за кулисном методе data
создает очень специальное поле в object
, называемом "jQuery" + now()
, помещает туда следующий id потока уникальных идентификаторов, таких как
id = elem[ expando ] = ++uuid;
Я бы предложил использовать тот же метод, что и Джон Ресиг, очевидно, знает все, что есть о JavaScript, и его метод основан на всех этих знаниях.
data
имеет недостатки. См. Например, stackoverflow.com/questions/1915341/… . Кроме того, Джон Ресиг отнюдь не знает все, что нужно знать о JavaScript, и полагая, что он это не поможет вам в качестве разработчика JavaScript.
– Tim Down
4 January 2010 в 10:51
Object.prototype
... – James 4 January 2010 в 11:52object.hasOwnProperty(member)
при использовании циклаfor..in
. Это хорошо зарекомендовавшая себя практика, и это обеспечивается jslint – Justin Johnson 5 January 2010 в 00:01defineProperty(…, {enumerable:false})
. И сам методuid
должен быть в пространстве именObject
– Bergi 19 December 2012 в 00:16