Why is PERSON not a ref class? - class

I don't understand why compiler thinks PERSON is NOT a ref class:
: error C2811: 'Runner' : cannot
inherit from 'Person', a ref class can
only inherit from a ref class or
interface class
I tried....
adding mscorlib.dll to the header files: #using..etc...<> - didn't work.
making Person an abstract class - didn't work (Im glad since I imagined that to be a instantiatable?? class)
I list the two header files first. Then their cose is listed later if you need it.
PERSON.H
#pragma once
using namespace System;
ref class Person
{
private:
void copy_ptr_data(Person%);
void delete_ptr_data(void);
public:
property String^ Name;
property String^ Age;
Person(String^ name, String^ age);
Person(Person%);
Person% operator= (Person%);
bool operator==(Person%);
bool operator!=(Person%);
virtual ~Person(void);
};
RUNNER.H
#pragma once
#include "Person.h"
using namespace System;
ref class Runner : public Person
{
private:
void copy_ptr_data(Runner%);
void delete_ptr_data(void);
public:
property String^ Time;
property String^ Rank;
Runner(String^ name, String^ age, String^ time);
Runner(Runner%);
Runner% operator= (Runner%);
bool operator==(Runner%);
bool operator!=(Runner%);
~Runner(void);
};
PERSON.CPP
#include "StdAfx.h"
#include "Person.h"
Person::Person(String^ name, String^ age)
{
Name = name;
Age = age;
}
Person::Person(Person% p)
{
Name = p.Name;
Age = p.Age;
copy_ptr_data(p);
}
Person% Person::operator= (Person% p)
{
// prevent self-assignment
if (this == %p) {
return *this;
}
// deallocate/reallocate/assign dynamic memory
delete_ptr_data();
copy_ptr_data(p);
// assign non-dynamic memory
Name = p.Name;
Age = p.Age;
return *this;
}
bool Person::operator==(Person% p)
{
if ((Name == p.Name) &&
(Age == p.Age))
return 1;
return 0;
}
bool Person::operator!=(Person% p)
{
return !(Person::operator==(p));
}
Person::~Person(void)
{
delete_ptr_data();
}
void Person::copy_ptr_data(Person% p)
{
return;
}
void Person::delete_ptr_data()
{
return;
}
RUNNER.CPP
#include "StdAfx.h"
#include "Runner.h"
Runner::Runner(String^ name, String^ age, String^ time) : Person(name, age)
{
Time = time;
Rank = nullptr;
}
Runner::Runner(Runner% r) : Person(r)
{
Time = r.Time;
Time = r.Rank;
copy_ptr_data(r);
}
Runner% Runner::operator= (Runner% r)
{
// handle self assignment
if (this == %r) return *this;
// handle base class portion
Person::operator=(r);
// handle dynamic portion
delete_ptr_data();
copy_ptr_data(r);
// handle non-dynamic portion
Time = r.Time;
Rank = r.Rank;
return *this;
}
bool Runner::operator==(Runner% r)
{
if ((Person::operator==(r)) &&
(Time == r.Time) &&
(Rank == r.Rank))
return 1;
return 0;
}
bool Runner::operator!=(Runner% r)
{
return !(Runner::operator==(r));
}
Runner::~Runner(void)
{
}
void Runner::copy_ptr_data(Runner% r)
{
return;
}
void Runner::delete_ptr_data()
{
return;
}

Shouldn't you be putting:
#using <mscorlib.dll>
at the top of your header files? I'm not sure if that would fix the issue to be honest.
Try making your Person class abstract.

Related

mybatis interceptor throw Reflection exception affects cpu performence

I had implement a interceptor of myabtis. but we found a problem, execute interceptor lead to throw so many IllegalAccessException, it affects cpu performence
Shown below is where the problem is, why did not check access permision of feild befor executed code "field.get(target)".
public class GetFieldInvoker implements Invoker {
private final Field field;
public GetFieldInvoker(Field field) {
this.field = field;
}
#Override
public Object invoke(Object target, Object[] args) throws IllegalAccessException {
try {
return field.get(target);
} catch (IllegalAccessException e) {
if (Reflector.canControlMemberAccessible()) {
field.setAccessible(true);
return field.get(target);
} else {
throw e;
}
}
}
#Override
public Class<?> getType() {
return field.getType();
}
}
the intercepor of mine:
#Intercepts({
#Signature(
type = StatementHandler.class,
method = "prepare",
args = {Connection.class, Integer.class})
})
public class SqlIdInterceptor implements Interceptor {
private static final int MAX_LEN = 256;
private final RoomboxLogger logger = RoomboxLogManager.getLogger();
#Override
public Object intercept(Invocation invocation) throws Throwable {
StatementHandler statementHandler = realTarget(invocation.getTarget());
MetaObject metaObject = SystemMetaObject.forObject(statementHandler);
BoundSql boundSql = (BoundSql) metaObject.getValue("delegate.boundSql");
String originalSql = boundSql.getSql();
MappedStatement mappedStatement =
(MappedStatement) metaObject.getValue("delegate.mappedStatement");
String id = mappedStatement.getId();
if (id != null) {
int len = id.length();
if (len > MAX_LEN) {
logger.warn("too long id", "id", id, "len", len);
}
}
String newSQL = "# " + id + "\n" + originalSql;
metaObject.setValue("delegate.boundSql.sql", newSQL);
return invocation.proceed();
}
#SuppressWarnings("unchecked")
public static <T> T realTarget(Object target) {
if (Proxy.isProxyClass(target.getClass())) {
MetaObject metaObject = SystemMetaObject.forObject(target);
return realTarget(metaObject.getValue("h.target"));
}
return (T) target;
}
}
Flame Graph
enter image description here
enter image description here
I need help, how to avoid throw exceptions, is any other way to reslove this problem?
thanks.

MVVM AsyncExecute causing lag

AsyncExecute method causing lag in my treeview application when I am expanding a branch.
Important parts of my TreeView
public DirectoryItemViewModel(string fullPath, DirectoryItemType type, long size)
{
this.ExpandCommand = new AsyncCommand(Expand, CanExecute);
this.FullPath = fullPath;
this.Type = type;
this.Size = size;
this.ClearChildren();
}
public bool CanExecute()
{
return !isBusy;
}
public IAsyncCommand ExpandCommand { get; set; }
private async Task Expand()
{
isBusy = true;
if (this.Type == DirectoryItemType.File)
{
return;
}
List<Task<long>> tasks = new();
var children = DirectoryStructure.GetDirectoryContents(this.FullPath);
this.Children = new ObservableCollection<DirectoryItemViewModel>(
children.Select(content => new DirectoryItemViewModel(content.FullPath, content.Type, 0)));
//If I delete the remaining part of code in this method everything works fine,
in my idea it should output the folders without lag, and then start calculating their size in other threads, but it first lags for 1-2 sec, then output the content of the folder, and then start calculating.
foreach (var item in children)
{
if (item.Type == DirectoryItemType.Folder)
{
tasks.Add(Task.Run(() => GetDirectorySize(new DirectoryInfo(item.FullPath))));
}
}
var results = await Task.WhenAll(tasks);
for (int i = 0; i < results.Length; i++)
{
Children[i].Size = results[i];
}
isBusy = false;
}
My command Interface and class
public interface IAsyncCommand : ICommand
{
Task ExecuteAsync();
bool CanExecute();
}
public class AsyncCommand : IAsyncCommand
{
public event EventHandler CanExecuteChanged;
private bool _isExecuting;
private readonly Func<Task> _execute;
private readonly Func<bool> _canExecute;
public AsyncCommand(
Func<Task> execute,
Func<bool> canExecute = null)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute()
{
return !_isExecuting && (_canExecute?.Invoke() ?? true);
}
public async Task ExecuteAsync()
{
if (CanExecute())
{
try
{
_isExecuting = true;
await _execute();
}
finally
{
_isExecuting = false;
}
}
RaiseCanExecuteChanged();
}
public void RaiseCanExecuteChanged()
{
CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
bool ICommand.CanExecute(object parameter)
{
return CanExecute();
}
void ICommand.Execute(object parameter)
{
//I suppose that here is the problem cause IDE is hinting me that I am not awaiting here, but I don't know how to change it if it is.
ExecuteAsync();
}
}

Unity, PropertyDrawer.GetPropertyHeight doesn't get called in multiple arrays on element change

I've started rewriting my Curve tool to deal with problem of drawing it in array and other reasons. All was well till I tried to click between editors in array and list elements. Sometimes Previously edited element retains its height until other element of that collection gets edited or curve field gets edited. I have no idea how to tell Unity it should refresh field heights. I've tried EditorUtility.SetDirty(targetObject); with or without EditorGUI.BeginChangeCheck(); EditorGUI.EndChangeCheck();
Number on left is OtherCurve.z, it's a way to deferenciate which PropertyDrawer you are debugging in code. Labels are temporal.
public class OtherTestScript : MonoBehaviour
{
public OtherCurve curve;
public OtherCurve[] curveArray;
public List<OtherCurve> curveList;
}
Curve tool repository at last commit with the issue
To test download this commit code and put it in Assets/Plugins/ and add these to your Packages/manifest.json:
"st.one-line": "https://github.com/slavniyteo/one-line.git#master",
"st.rect-ex": "https://github.com/slavniyteo/rect-ex.git#master",
This code stays there, I'm not going to hide it from public or rewrite history of the repository.
After trying to recreate this behaviour on a simpler example I've found out that my technique works...
Edited: Appears that using GUI.Label(..) to draw label in Editor and not using any other EditorGUI components caused GetPropertyHeight not being called. So If I wouldn't stop at this bug, it would disappear when I replaced that GUI.Label placeholder with actually meaningful code. I feel empty for wasting that much time to figure this out.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.SceneManagement;
using System.Reflection;
using System.Linq;
using System.Text.RegularExpressions;
#if UNITY_EDITOR
using UnityEditor;
using UnityEditor.SceneManagement;
#endif
public class PropertyThing : MonoBehaviour
{
public CustomThing thing;
public List<CustomThing> thingList;
public CustomThing[] thingArray;
[Serializable]
public class CustomThing
{
#if UNITY_EDITOR
public bool _isEdited;
#endif
public string field;
}
#if UNITY_EDITOR
[CustomPropertyDrawer(typeof(CustomThing))]
public class CustomThingInspector : PropertyDrawer
{
private UnityEngine.Object targetObject;
private CustomThing value;
private static Action FinishCurrentEditorAction;
private static void FinishCurrentEditor() => FinishCurrentEditorAction();
private static void FinishCurrentEditor(Scene s) => FinishCurrentEditorAction();
private string EditButtonText(bool editing) => editing ? "Stop Edit" : "Edit";
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
GetObjects(property);
return value._isEdited ? 38 : 18;
}
private void GetObjects(SerializedProperty property)
{
targetObject = property.serializedObject.targetObject;
value = property.GetValue<CustomThing>();
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var c = GUI.color;
GetObjects(property);
EditorGUI.BeginProperty(position, label, property);
var firstline = new Rect(position.x, position.y, position.width, 18);
var editor = new Rect(position.x, position.y + 20, position.width, position.height - 20);
var brect = EditorGUI.PrefixLabel(firstline, label);
if (value._isEdited) GUI.color = Color.red * .6666f + Color.white * .3333f;
if (GUI.Button(brect, EditButtonText(value._isEdited)))
{
EditPressed();
}
GUI.color = c;
if (value._isEdited)
EditorGUI.PropertyField(editor, property.FindPropertyRelative("field"));
EditorGUI.EndProperty();
GUI.color = c;
}
private void EditPressed()
{
value._isEdited = !value._isEdited;
if (value._isEdited)
StartEditor(value);
else
FinishEditor(value);
}
private void StartEditor(CustomThing thing)
{
var capturedThing = thing;
FinishCurrentEditorAction?.Invoke();
FinishCurrentEditorAction = () => {
FinishEditor(capturedThing);
EditorUtility.SetDirty(targetObject);
FinishCurrentEditorAction = null;
};
capturedThing._isEdited = true;
SceneView.duringSceneGui += OnEditorSceneView;
}
private void FinishEditor(CustomThing thing)
{
Selection.selectionChanged -= FinishCurrentEditor;
EditorSceneManager.sceneClosed -= FinishCurrentEditor;
AssemblyReloadEvents.beforeAssemblyReload -= FinishCurrentEditor;
SceneView.duringSceneGui -= OnEditorSceneView;
thing._isEdited = false;
FinishCurrentEditorAction = null;
}
private void OnEditorSceneView(SceneView obj)
{
if (targetObject is Component c)
Handles.Label(c.transform.position, c.gameObject.name);
else
Handles.Label(Vector3.zero, targetObject.name);
}
}
#endif
}
public static class SerializedUtility
{
public static T GetValue<T>(this SerializedProperty property) where T : class
{
object obj = property.serializedObject.targetObject;
string path = property.propertyPath.Replace(".Array.data", "");
string[] fieldStructure = path.Split('.');
Regex rgx = new Regex(#"\[\d+\]");
for (int i = 0; i < fieldStructure.Length; i++)
{
if (fieldStructure[i].Contains("["))
{
int index = System.Convert.ToInt32(new string(fieldStructure[i].Where(c => char.IsDigit(c)).ToArray()));
obj = GetFieldValueWithIndex(rgx.Replace(fieldStructure[i], ""), obj, index);
}
else
{
obj = GetFieldValue(fieldStructure[i], obj);
}
}
return (T)obj;
}
public static bool SetValue<T>(this SerializedProperty property, T value) where T : class
{
object obj = property.serializedObject.targetObject;
string path = property.propertyPath.Replace(".Array.data", "");
string[] fieldStructure = path.Split('.');
Regex rgx = new Regex(#"\[\d+\]");
for (int i = 0; i < fieldStructure.Length - 1; i++)
{
if (fieldStructure[i].Contains("["))
{
int index = System.Convert.ToInt32(new string(fieldStructure[i].Where(c => char.IsDigit(c)).ToArray()));
obj = GetFieldValueWithIndex(rgx.Replace(fieldStructure[i], ""), obj, index);
}
else
{
obj = GetFieldValue(fieldStructure[i], obj);
}
}
string fieldName = fieldStructure.Last();
if (fieldName.Contains("["))
{
int index = System.Convert.ToInt32(new string(fieldName.Where(c => char.IsDigit(c)).ToArray()));
return SetFieldValueWithIndex(rgx.Replace(fieldName, ""), obj, index, value);
}
else
{
Debug.Log(value);
return SetFieldValue(fieldName, obj, value);
}
}
private static object GetFieldValue(string fieldName, object obj, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
{
FieldInfo field = obj.GetType().GetField(fieldName, bindings);
if (field != null)
{
return field.GetValue(obj);
}
return default(object);
}
private static object GetFieldValueWithIndex(string fieldName, object obj, int index, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
{
FieldInfo field = obj.GetType().GetField(fieldName, bindings);
if (field != null)
{
object list = field.GetValue(obj);
if (list.GetType().IsArray)
{
return ((object[])list)[index];
}
else if (list is IEnumerable)
{
return ((IList)list)[index];
}
}
return default(object);
}
public static bool SetFieldValue(string fieldName, object obj, object value, bool includeAllBases = false, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
{
FieldInfo field = obj.GetType().GetField(fieldName, bindings);
if (field != null)
{
field.SetValue(obj, value);
return true;
}
return false;
}
public static bool SetFieldValueWithIndex(string fieldName, object obj, int index, object value, bool includeAllBases = false, BindingFlags bindings = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)
{
FieldInfo field = obj.GetType().GetField(fieldName, bindings);
if (field != null)
{
object list = field.GetValue(obj);
if (list.GetType().IsArray)
{
((object[])list)[index] = value;
return true;
}
else if (value is IEnumerable)
{
((IList)list)[index] = value;
return true;
}
}
return false;
}
}

Problems serializing a c++\cli vector

I am trying to serialize a vector of accounts but I keep getting the following exception :-
To be XML serializable, types which inherit from ICollection must have an implementation of Add(Account) at all levels of their inheritance hierarchy. cliext.vector does not implement Add(Account).
I have added an Add(Account) function to my class but it still doesn't work. I'm relatively new to C++ so my code is probably poor or might not be the correct way of doing what I want.
All help appreciated.
here is the main function :-
// TestDotNetXML.cpp : main project file.
#include "stdafx.h"
using namespace System;
using namespace System::Xml;
using namespace System::Xml::Serialization;
int main(array<System::String ^> ^args)
{
AccountList^ MyAccountList = gcnew AccountList;
Account^ Account1 = gcnew Account("1","1","1","1");
Account^ Account2 = gcnew Account("2","2","2","2");
Account Account3;
Account3.setAccountName("3");
Account3.setUserName("3");
Account3.setPassword("3");
Account3.setDescription("3");
MyAccountList->Add(Account1);
MyAccountList->Add(Account2);
MyAccountList->Add(Account3);
try
{
XmlSerializer^ x = gcnew XmlSerializer(MyAccountList->GetType());
x->Serialize(Console::Out, MyAccountList);
}
catch(System::InvalidOperationException^ ex)
{
Console::WriteLine(ex->InnerException);
}
Console::WriteLine();
Console::ReadLine();
return 0;
}
The Account class
Account.h
#pragma once
using namespace System;
[Serializable]
public ref class Account
{
public:
String^ accountName;
String^ userName;
String^ password;
String^ description;
public:
Account(String^ accountName, String^ userName, String^ password, String^ description);
Account(void);
Account(const Account% ob);
Account% operator=(const Account% ob);
~Account(void);
String^ getAccountName();
void setAccountName(String^ accountName);
String^ getUserName();
void setUserName(String^ userName);
String^ getPassword();
void setPassword(String^ password);
String^ getDescription();
void setDescription(String^ description);
};
Account.cpp
#include "stdafx.h"
#include "Account.h"
Account::Account(String^ accountName, String^ userName, String^ password, String^ description)
{
this->accountName = gcnew String(accountName);
this->userName = gcnew String(userName);
this->password = gcnew String(password);
this->description = gcnew String(description);
}
Account::Account(void)
{
}
Account::Account(const Account %ob)
{
accountName = ob.accountName;
userName = ob.userName;
password = ob.password;
description = ob.description;
}
Account% Account::operator=(const Account% ob)
{
if(this != %ob)
{
accountName = ob.accountName;
userName = ob.userName;
password = ob.password;
description = ob.description;
}
return *this;
}
Account::~Account(void)
{
this->accountName = gcnew String("");
this->userName = gcnew String("");
this->password = gcnew String("");
this->description = gcnew String("");
}
String^ Account::getAccountName()
{
return this->accountName;
}
void Account::setAccountName(String^ accountName)
{
this->accountName = accountName;
}
String^ Account::getUserName()
{
return this->userName;
}
void Account::setUserName(String^ userName)
{
this->userName = accountName;
}
String^ Account::getPassword()
{
return this->password;
}
void Account::setPassword(String^ password)
{
this->password = password;
}
String^ Account::getDescription()
{
return this->description;
}
void Account::setDescription(String^ description)
{
this->description = description;
}
AccountList.h
#pragma once
#include <cliext/vector>
#include "Account.h"
using namespace cliext;
public ref class AccountList
{
public:
vector<Account^>^ List;
public:
AccountList(void);
void Add(Account^ anAccount);
void Add(Account anAccount);
void Remove(Account^ anAccount);
bool Exists(Account^ anAccount);
Account^ getAccout(String^ accountName);
vector<Account^>^ getList(void);
unsigned int stopLNK2022() { return List->size(); }
};
AccountList.cpp
#include "stdafx.h"
#include "AccountList.h"
#include "Account.h"
AccountList::AccountList(void)
{
List = gcnew vector<Account^>;
}
void AccountList::Add(Account^ anAccount)
{
this->List->push_back(anAccount);
}
void AccountList::Add(Account anAccount)
{
Account^ ptrAccount = gcnew Account(
anAccount.getAccountName(),
anAccount.getUserName(),
anAccount.getPassword(),
anAccount.getDescription()
);
this->List->push_back(ptrAccount);
}
void AccountList::Remove(Account^ anAccount)
{
vector<Account^>::iterator Iter;
for(Iter = List->begin(); Iter != List->end(); Iter++)
{
if((safe_cast<Account^>(*Iter))->getAccountName()
== anAccount->getAccountName())
{
List->erase(Iter);
}
}
}
bool AccountList::Exists(Account^ anAccount)
{
vector<Account^>::iterator Iter;
for(Iter = List->begin(); Iter != List->end(); Iter++)
{
if((safe_cast<Account^>(*Iter))->getAccountName()
== anAccount->getAccountName())
{
return true;
}
}
return false;
}
vector<Account^>^ AccountList::getList(void)
{
return List;
}
Account^ AccountList::getAccout(String^ accountName)
{
vector<Account^>::iterator Iter;
for(Iter = List->begin(); Iter != List->end(); Iter++)
{
String^ test = (safe_cast<Account^>(*Iter))->getAccountName();
if((safe_cast<Account^>(*Iter))->getAccountName()
== accountName)
{
return safe_cast<Account^>(*Iter);
}
}
return nullptr;
}

C# IEnumerable Interface

I am trying to understand this example from a MSDN article, to my understanding with the IEnumberable interface, we will be able to use Foreach to loop through the class collection, I am confused at the Main method, why don't we just use:
foreach (Person p in peopleArray)
Console.WriteLine(p.firstName + " " + p.lastName);
instead of
People peopleList = new People(peopleArray);
foreach (Person p in peopleList)
Console.WriteLine(p.firstName + " " + p.lastName);
Example:
using System;
using System.Collections;
public class Person
{
public Person(string fName, string lName)
{
this.firstName = fName;
this.lastName = lName;
}
public string firstName;
public string lastName;
}
public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people = new Person[pArray.Length];
for (int i = 0; i < pArray.Length; i++)
{
_people[i] = pArray[i];
}
}
IEnumerator IEnumerable.GetEnumerator()
{
return (IEnumerator) GetEnumerator();
}
public PeopleEnum GetEnumerator()
{
return new PeopleEnum(_people);
}
}
public class PeopleEnum : IEnumerator
{
public Person[] _people;
// Enumerators are positioned before the first element
// until the first MoveNext() call.
int position = -1;
public PeopleEnum(Person[] list)
{
_people = list;
}
public bool MoveNext()
{
position++;
return (position < _people.Length);
}
public void Reset()
{
position = -1;
}
object IEnumerator.Current
{
get
{
return Current;
}
}
public Person Current
{
get
{
try
{
return _people[position];
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
}
class App
{
static void Main()
{
Person[] peopleArray = new Person[3]
{
new Person("John", "Smith"),
new Person("Jim", "Johnson"),
new Person("Sue", "Rabon"),
};
People peopleList = new People(peopleArray);
foreach (Person p in peopleList)
Console.WriteLine(p.firstName + " " + p.lastName);
}
}
You're right, you could simply use the first version because arrays implement IEnumerable.
The reason they chose to iterate over People is simply for academic purposes; to demonstrate how iterators work (and how to implement IEnumerable). If they simply iterated over peoplearray, they wouldn't be using the People class, which is the main focus of that example.